Skip to content

Commit

Permalink
Merge branch 'datahub-project:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
hsheth2 authored Jul 30, 2024
2 parents 3f6bb45 + 9321e94 commit 4b664ef
Show file tree
Hide file tree
Showing 28 changed files with 1,254 additions and 186 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ private Constants() {}
public static final String PROPERTIES_SCHEMA_FILE = "properties.graphql";
public static final String FORMS_SCHEMA_FILE = "forms.graphql";
public static final String ASSERTIONS_SCHEMA_FILE = "assertions.graphql";
public static final String COMMON_SCHEMA_FILE = "common.graphql";
public static final String INCIDENTS_SCHEMA_FILE = "incident.graphql";
public static final String CONTRACTS_SCHEMA_FILE = "contract.graphql";
public static final String CONNECTIONS_SCHEMA_FILE = "connection.graphql";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
import com.linkedin.datahub.graphql.generated.MLPrimaryKey;
import com.linkedin.datahub.graphql.generated.MLPrimaryKeyProperties;
import com.linkedin.datahub.graphql.generated.MatchedField;
import com.linkedin.datahub.graphql.generated.MetadataAttribution;
import com.linkedin.datahub.graphql.generated.Notebook;
import com.linkedin.datahub.graphql.generated.Owner;
import com.linkedin.datahub.graphql.generated.OwnershipTypeEntity;
Expand Down Expand Up @@ -284,6 +285,8 @@
import com.linkedin.datahub.graphql.resolvers.search.SearchAcrossEntitiesResolver;
import com.linkedin.datahub.graphql.resolvers.search.SearchAcrossLineageResolver;
import com.linkedin.datahub.graphql.resolvers.search.SearchResolver;
import com.linkedin.datahub.graphql.resolvers.settings.docPropagation.DocPropagationSettingsResolver;
import com.linkedin.datahub.graphql.resolvers.settings.docPropagation.UpdateDocPropagationSettingsResolver;
import com.linkedin.datahub.graphql.resolvers.settings.user.UpdateCorpUserViewsSettingsResolver;
import com.linkedin.datahub.graphql.resolvers.settings.view.GlobalViewsSettingsResolver;
import com.linkedin.datahub.graphql.resolvers.settings.view.UpdateGlobalViewsSettingsResolver;
Expand Down Expand Up @@ -695,7 +698,8 @@ public GmsGraphQLEngine(final GmsGraphQLEngineArgs args) {
businessAttributeType));
this.loadableTypes = new ArrayList<>(entityTypes);
// Extend loadable types with types from the plugins
// This allows us to offer search and browse capabilities out of the box for those types
// This allows us to offer search and browse capabilities out of the box for
// those types
for (GmsGraphQLPlugin plugin : this.graphQLPlugins) {
this.entityTypes.addAll(plugin.getEntityTypes());
Collection<? extends LoadableType<?, ?>> pluginLoadableTypes = plugin.getLoadableTypes();
Expand Down Expand Up @@ -790,6 +794,7 @@ public void configureRuntimeWiring(final RuntimeWiring.Builder builder) {
configureBusinessAttributeAssociationResolver(builder);
configureConnectionResolvers(builder);
configureDeprecationResolvers(builder);
configureMetadataAttributionResolver(builder);
}

private void configureOrganisationRoleResolvers(RuntimeWiring.Builder builder) {
Expand Down Expand Up @@ -843,7 +848,8 @@ public GraphQLEngine.Builder builder() {
.addSchema(fileBasedSchema(CONNECTIONS_SCHEMA_FILE))
.addSchema(fileBasedSchema(ASSERTIONS_SCHEMA_FILE))
.addSchema(fileBasedSchema(INCIDENTS_SCHEMA_FILE))
.addSchema(fileBasedSchema(CONTRACTS_SCHEMA_FILE));
.addSchema(fileBasedSchema(CONTRACTS_SCHEMA_FILE))
.addSchema(fileBasedSchema(COMMON_SCHEMA_FILE));

for (GmsGraphQLPlugin plugin : this.graphQLPlugins) {
List<String> pluginSchemaFiles = plugin.getSchemaFiles();
Expand Down Expand Up @@ -1087,8 +1093,10 @@ private void configureQueryResolvers(final RuntimeWiring.Builder builder) {
new BrowseV2Resolver(this.entityClient, this.viewService, this.formService))
.dataFetcher("businessAttribute", getResolver(businessAttributeType))
.dataFetcher(
"listBusinessAttributes",
new ListBusinessAttributesResolver(this.entityClient)));
"listBusinessAttributes", new ListBusinessAttributesResolver(this.entityClient))
.dataFetcher(
"docPropagationSettings",
new DocPropagationSettingsResolver(this.settingsService)));
}

private DataFetcher getEntitiesResolver() {
Expand Down Expand Up @@ -1340,7 +1348,11 @@ private void configureMutationResolvers(final RuntimeWiring.Builder builder) {
.dataFetcher(
"createForm", new CreateFormResolver(this.entityClient, this.formService))
.dataFetcher("deleteForm", new DeleteFormResolver(this.entityClient))
.dataFetcher("updateForm", new UpdateFormResolver(this.entityClient));
.dataFetcher("updateForm", new UpdateFormResolver(this.entityClient))
.dataFetcher(
"updateDocPropagationSettings",
new UpdateDocPropagationSettingsResolver(this.settingsService));

if (featureFlags.isBusinessAttributeEntityEnabled()) {
typeWiring
.dataFetcher(
Expand Down Expand Up @@ -2823,7 +2835,8 @@ private void configureContractResolvers(final RuntimeWiring.Builder builder) {
}

private void configurePolicyResolvers(final RuntimeWiring.Builder builder) {
// Register resolvers for "resolvedUsers" and "resolvedGroups" field of the Policy type.
// Register resolvers for "resolvedUsers" and "resolvedGroups" field of the
// Policy type.
builder.type(
"ActorFilter",
typeWiring ->
Expand Down Expand Up @@ -3176,4 +3189,20 @@ private void configureDeprecationResolvers(final RuntimeWiring.Builder builder)
new EntityTypeResolver(
entityTypes, (env) -> ((Deprecation) env.getSource()).getActorEntity())));
}

private void configureMetadataAttributionResolver(final RuntimeWiring.Builder builder) {
builder.type(
"MetadataAttribution",
typeWiring ->
typeWiring
.dataFetcher(
"actor",
new EntityTypeResolver(
entityTypes, (env) -> ((MetadataAttribution) env.getSource()).getActor()))
.dataFetcher(
"source",
new EntityTypeResolver(
entityTypes,
(env) -> ((MetadataAttribution) env.getSource()).getSource())));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,11 @@ public static boolean canManageForms(@Nonnull QueryContext context) {
PoliciesConfig.MANAGE_DOCUMENTATION_FORMS_PRIVILEGE);
}

public static boolean canManageFeatures(@Nonnull QueryContext context) {
return AuthUtil.isAuthorized(
context.getAuthorizer(), context.getActorUrn(), PoliciesConfig.MANAGE_FEATURES_PRIVILEGE);
}

public static boolean isAuthorized(
@Nonnull Authorizer authorizer,
@Nonnull String actor,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.linkedin.datahub.graphql.resolvers.settings.docPropagation;

import com.linkedin.datahub.graphql.QueryContext;
import com.linkedin.datahub.graphql.concurrency.GraphQLConcurrencyUtils;
import com.linkedin.datahub.graphql.generated.DocPropagationSettings;
import com.linkedin.metadata.service.SettingsService;
import com.linkedin.settings.global.GlobalSettingsInfo;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull;
import lombok.extern.slf4j.Slf4j;

/** Retrieves the Global Settings related to the Actions feature. */
@Slf4j
public class DocPropagationSettingsResolver
implements DataFetcher<CompletableFuture<DocPropagationSettings>> {

private final SettingsService _settingsService;

public DocPropagationSettingsResolver(final SettingsService settingsService) {
_settingsService = Objects.requireNonNull(settingsService, "settingsService must not be null");
}

@Override
public CompletableFuture<DocPropagationSettings> get(final DataFetchingEnvironment environment)
throws Exception {
final QueryContext context = environment.getContext();
return GraphQLConcurrencyUtils.supplyAsync(
() -> {
try {
final GlobalSettingsInfo globalSettings =
_settingsService.getGlobalSettings(context.getOperationContext());
final DocPropagationSettings defaultSettings = new DocPropagationSettings();
defaultSettings.setDocColumnPropagation(true);
return globalSettings != null && globalSettings.hasDocPropagation()
? mapDocPropagationSettings(globalSettings.getDocPropagation())
: defaultSettings;
} catch (Exception e) {
throw new RuntimeException("Failed to retrieve Action Settings", e);
}
},
this.getClass().getSimpleName(),
"get");
}

private static DocPropagationSettings mapDocPropagationSettings(
@Nonnull final com.linkedin.settings.global.DocPropagationFeatureSettings settings) {
final DocPropagationSettings result = new DocPropagationSettings();

// Map docColumnPropagation settings field
result.setDocColumnPropagation(settings.isColumnPropagationEnabled());

return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.linkedin.datahub.graphql.resolvers.settings.docPropagation;

import static com.linkedin.datahub.graphql.resolvers.ResolverUtils.*;

import com.linkedin.datahub.graphql.QueryContext;
import com.linkedin.datahub.graphql.authorization.AuthorizationUtils;
import com.linkedin.datahub.graphql.concurrency.GraphQLConcurrencyUtils;
import com.linkedin.datahub.graphql.exception.AuthorizationException;
import com.linkedin.datahub.graphql.generated.UpdateDocPropagationSettingsInput;
import com.linkedin.metadata.service.SettingsService;
import com.linkedin.settings.global.DocPropagationFeatureSettings;
import com.linkedin.settings.global.GlobalSettingsInfo;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull;

/** Resolver responsible for updating the actions settings. */
public class UpdateDocPropagationSettingsResolver
implements DataFetcher<CompletableFuture<Boolean>> {

private final SettingsService _settingsService;

public UpdateDocPropagationSettingsResolver(@Nonnull final SettingsService settingsService) {
_settingsService = Objects.requireNonNull(settingsService, "settingsService must not be null");
}

@Override
public CompletableFuture<Boolean> get(final DataFetchingEnvironment environment)
throws Exception {
final QueryContext context = environment.getContext();
final UpdateDocPropagationSettingsInput input =
bindArgument(environment.getArgument("input"), UpdateDocPropagationSettingsInput.class);

return GraphQLConcurrencyUtils.supplyAsync(
() -> {
if (AuthorizationUtils.canManageFeatures(context)) {
try {
// First, fetch the existing global settings. This does a R-M-F.
final GlobalSettingsInfo maybeGlobalSettings =
_settingsService.getGlobalSettings(context.getOperationContext());

final GlobalSettingsInfo newGlobalSettings =
maybeGlobalSettings != null ? maybeGlobalSettings : new GlobalSettingsInfo();

final DocPropagationFeatureSettings newDocPropagationSettings =
newGlobalSettings.hasDocPropagation()
? newGlobalSettings.getDocPropagation()
: new DocPropagationFeatureSettings().setEnabled(true);

// Next, patch the actions settings.
updateDocPropagationSettings(newDocPropagationSettings, input);
newGlobalSettings.setDocPropagation(newDocPropagationSettings);

// Finally, write back to GMS.
_settingsService.updateGlobalSettings(
context.getOperationContext(), newGlobalSettings);
return true;
} catch (Exception e) {
throw new RuntimeException(
String.format("Failed to update action settings! %s", input), e);
}
}
throw new AuthorizationException(
"Unauthorized to perform this action. Please contact your DataHub administrator.");
},
this.getClass().getSimpleName(),
"get");
}

private static void updateDocPropagationSettings(
@Nonnull final com.linkedin.settings.global.DocPropagationFeatureSettings settings,
@Nonnull final UpdateDocPropagationSettingsInput input) {
settings.setColumnPropagationEnabled(input.getDocColumnPropagation());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.linkedin.datahub.graphql.types.common.mappers;

import com.linkedin.common.urn.Urn;
import com.linkedin.datahub.graphql.QueryContext;
import com.linkedin.datahub.graphql.generated.DataHubConnection;
import com.linkedin.datahub.graphql.generated.Documentation;
import com.linkedin.datahub.graphql.generated.DocumentationAssociation;
import com.linkedin.datahub.graphql.generated.EntityType;
import com.linkedin.datahub.graphql.types.mappers.ModelMapper;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class DocumentationMapper
implements ModelMapper<com.linkedin.common.Documentation, Documentation> {

public static final DocumentationMapper INSTANCE = new DocumentationMapper();

public static Documentation map(
@Nullable final QueryContext context,
@Nonnull final com.linkedin.common.Documentation metadata) {
return INSTANCE.apply(context, metadata);
}

@Override
public Documentation apply(
@Nullable final QueryContext context,
@Nonnull final com.linkedin.common.Documentation input) {
final Documentation result = new Documentation();
result.setDocumentations(
input.getDocumentations().stream()
.map(docAssociation -> mapDocAssociation(context, docAssociation))
.collect(Collectors.toList()));
return result;
}

private DocumentationAssociation mapDocAssociation(
@Nullable final QueryContext context,
@Nonnull final com.linkedin.common.DocumentationAssociation association) {
final DocumentationAssociation result = new DocumentationAssociation();
result.setDocumentation(association.getDocumentation());
if (association.getAttribution() != null) {
result.setAttribution(MetadataAttributionMapper.map(context, association.getAttribution()));
}
return result;
}

private DataHubConnection mapConnectionEntity(@Nonnull final Urn urn) {
DataHubConnection connection = new DataHubConnection();
connection.setUrn(urn.toString());
connection.setType(EntityType.DATAHUB_CONNECTION);
return connection;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.linkedin.datahub.graphql.types.common.mappers;

import com.linkedin.datahub.graphql.QueryContext;
import com.linkedin.datahub.graphql.generated.MetadataAttribution;
import com.linkedin.datahub.graphql.types.mappers.ModelMapper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class MetadataAttributionMapper
implements ModelMapper<com.linkedin.common.MetadataAttribution, MetadataAttribution> {

public static final MetadataAttributionMapper INSTANCE = new MetadataAttributionMapper();

public static MetadataAttribution map(
@Nullable final QueryContext context,
@Nonnull final com.linkedin.common.MetadataAttribution metadata) {
return INSTANCE.apply(context, metadata);
}

@Override
public MetadataAttribution apply(
@Nullable final QueryContext context,
@Nonnull final com.linkedin.common.MetadataAttribution input) {
final MetadataAttribution result = new MetadataAttribution();
result.setTime(input.getTime());
result.setActor(UrnToEntityMapper.map(context, input.getActor()));
if (input.getSource() != null) {
result.setSource(UrnToEntityMapper.map(context, input.getSource()));
}
if (input.getSourceDetail() != null) {
result.setSourceDetail(StringMapMapper.map(context, input.getSourceDetail()));
}
return result;
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package com.linkedin.datahub.graphql.types.schemafield;

import static com.linkedin.metadata.Constants.BUSINESS_ATTRIBUTE_ASPECT;
import static com.linkedin.metadata.Constants.STRUCTURED_PROPERTIES_ASPECT_NAME;
import static com.linkedin.metadata.Constants.*;

import com.linkedin.businessattribute.BusinessAttributes;
import com.linkedin.common.Documentation;
import com.linkedin.common.urn.Urn;
import com.linkedin.datahub.graphql.QueryContext;
import com.linkedin.datahub.graphql.generated.EntityType;
import com.linkedin.datahub.graphql.generated.SchemaFieldEntity;
import com.linkedin.datahub.graphql.types.businessattribute.mappers.BusinessAttributesMapper;
import com.linkedin.datahub.graphql.types.common.mappers.DocumentationMapper;
import com.linkedin.datahub.graphql.types.common.mappers.UrnToEntityMapper;
import com.linkedin.datahub.graphql.types.common.mappers.util.MappingHelper;
import com.linkedin.datahub.graphql.types.mappers.ModelMapper;
Expand Down Expand Up @@ -46,6 +47,10 @@ public SchemaFieldEntity apply(
(((schemaField, dataMap) ->
schemaField.setBusinessAttributes(
BusinessAttributesMapper.map(new BusinessAttributes(dataMap), entityUrn)))));
mappingHelper.mapToResult(
DOCUMENTATION_ASPECT_NAME,
(entity, dataMap) ->
entity.setDocumentation(DocumentationMapper.map(context, new Documentation(dataMap))));
return result;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.linkedin.datahub.graphql.types.schemafield;

import static com.linkedin.metadata.Constants.BUSINESS_ATTRIBUTE_ASPECT;
import static com.linkedin.metadata.Constants.SCHEMA_FIELD_ENTITY_NAME;
import static com.linkedin.metadata.Constants.STRUCTURED_PROPERTIES_ASPECT_NAME;
import static com.linkedin.metadata.Constants.*;

import com.google.common.collect.ImmutableSet;
import com.linkedin.common.urn.Urn;
Expand Down Expand Up @@ -32,7 +30,8 @@ public class SchemaFieldType
implements com.linkedin.datahub.graphql.types.EntityType<SchemaFieldEntity, String> {

public static final Set<String> ASPECTS_TO_FETCH =
ImmutableSet.of(STRUCTURED_PROPERTIES_ASPECT_NAME, BUSINESS_ATTRIBUTE_ASPECT);
ImmutableSet.of(
STRUCTURED_PROPERTIES_ASPECT_NAME, BUSINESS_ATTRIBUTE_ASPECT, DOCUMENTATION_ASPECT_NAME);

private final EntityClient _entityClient;
private final FeatureFlags _featureFlags;
Expand Down
Loading

0 comments on commit 4b664ef

Please sign in to comment.