Skip to content

Commit

Permalink
Merge branch 'master' into master+looker-ingestion-guide
Browse files Browse the repository at this point in the history
  • Loading branch information
yoonhyejin authored Sep 20, 2023
2 parents 545e2fb + 47b7e29 commit 3e63527
Show file tree
Hide file tree
Showing 112 changed files with 3,339 additions and 464 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
import com.linkedin.datahub.graphql.generated.Notebook;
import com.linkedin.datahub.graphql.generated.Owner;
import com.linkedin.datahub.graphql.generated.OwnershipTypeEntity;
import com.linkedin.datahub.graphql.generated.ParentDomainsResult;
import com.linkedin.datahub.graphql.generated.PolicyMatchCriterionValue;
import com.linkedin.datahub.graphql.generated.QueryEntity;
import com.linkedin.datahub.graphql.generated.QuerySubject;
Expand Down Expand Up @@ -124,6 +125,7 @@
import com.linkedin.datahub.graphql.resolvers.domain.DeleteDomainResolver;
import com.linkedin.datahub.graphql.resolvers.domain.DomainEntitiesResolver;
import com.linkedin.datahub.graphql.resolvers.domain.ListDomainsResolver;
import com.linkedin.datahub.graphql.resolvers.domain.ParentDomainsResolver;
import com.linkedin.datahub.graphql.resolvers.domain.SetDomainResolver;
import com.linkedin.datahub.graphql.resolvers.domain.UnsetDomainResolver;
import com.linkedin.datahub.graphql.resolvers.embed.UpdateEmbedResolver;
Expand Down Expand Up @@ -186,6 +188,7 @@
import com.linkedin.datahub.graphql.resolvers.mutate.BatchSetDomainResolver;
import com.linkedin.datahub.graphql.resolvers.mutate.BatchUpdateDeprecationResolver;
import com.linkedin.datahub.graphql.resolvers.mutate.BatchUpdateSoftDeletedResolver;
import com.linkedin.datahub.graphql.resolvers.mutate.MoveDomainResolver;
import com.linkedin.datahub.graphql.resolvers.mutate.MutableTypeBatchResolver;
import com.linkedin.datahub.graphql.resolvers.mutate.MutableTypeResolver;
import com.linkedin.datahub.graphql.resolvers.mutate.RemoveLinkResolver;
Expand Down Expand Up @@ -944,6 +947,7 @@ private void configureMutationResolvers(final RuntimeWiring.Builder builder) {
.dataFetcher("removeGroup", new RemoveGroupResolver(this.entityClient))
.dataFetcher("updateUserStatus", new UpdateUserStatusResolver(this.entityClient))
.dataFetcher("createDomain", new CreateDomainResolver(this.entityClient, this.entityService))
.dataFetcher("moveDomain", new MoveDomainResolver(this.entityService, this.entityClient))
.dataFetcher("deleteDomain", new DeleteDomainResolver(entityClient))
.dataFetcher("setDomain", new SetDomainResolver(this.entityClient, this.entityService))
.dataFetcher("batchSetDomain", new BatchSetDomainResolver(this.entityService))
Expand Down Expand Up @@ -1029,6 +1033,13 @@ private void configureGenericEntityResolvers(final RuntimeWiring.Builder builder
.dataFetcher("entities", new EntityTypeBatchResolver(entityTypes,
(env) -> ((BrowseResults) env.getSource()).getEntities()))
)
.type("ParentDomainsResult", typeWiring -> typeWiring
.dataFetcher("domains", new EntityTypeBatchResolver(entityTypes,
(env) -> {
final ParentDomainsResult result = env.getSource();
return result != null ? result.getDomains() : null;
}))
)
.type("EntityRelationshipLegacy", typeWiring -> typeWiring
.dataFetcher("entity", new EntityTypeResolver(entityTypes,
(env) -> ((EntityRelationshipLegacy) env.getSource()).getEntity()))
Expand Down Expand Up @@ -1675,8 +1686,8 @@ private void configureGlossaryRelationshipResolvers(final RuntimeWiring.Builder
private void configureDomainResolvers(final RuntimeWiring.Builder builder) {
builder.type("Domain", typeWiring -> typeWiring
.dataFetcher("entities", new DomainEntitiesResolver(this.entityClient))
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient)
)
.dataFetcher("parentDomains", new ParentDomainsResolver(this.entityClient))
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient))
);
builder.type("DomainAssociation", typeWiring -> typeWiring
.dataFetcher("domain",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public enum DataHubGraphQLErrorCode {
BAD_REQUEST(400),
UNAUTHORIZED(403),
NOT_FOUND(404),
CONFLICT(409),
SERVER_ERROR(500);

private final int _code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ public class FeatureFlags {
private PreProcessHooks preProcessHooks;
private boolean showAcrylInfo = false;
private boolean showAccessManagement = false;
private boolean nestedDomainsEnabled = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ public CompletableFuture<AppConfig> get(final DataFetchingEnvironment environmen
.setShowBrowseV2(_featureFlags.isShowBrowseV2())
.setShowAcrylInfo(_featureFlags.isShowAcrylInfo())
.setShowAccessManagement(_featureFlags.isShowAccessManagement())
.setNestedDomainsEnabled(_featureFlags.isNestedDomainsEnabled())
.build();

appConfig.setFeatureFlags(featureFlagsConfig);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package com.linkedin.datahub.graphql.resolvers.domain;

import com.linkedin.common.AuditStamp;
import com.linkedin.common.urn.Urn;
import com.linkedin.common.urn.UrnUtils;
import com.linkedin.data.template.SetMode;
import com.linkedin.datahub.graphql.QueryContext;
import com.linkedin.datahub.graphql.authorization.AuthorizationUtils;
import com.linkedin.datahub.graphql.exception.AuthorizationException;
import com.linkedin.datahub.graphql.exception.DataHubGraphQLErrorCode;
import com.linkedin.datahub.graphql.exception.DataHubGraphQLException;
import com.linkedin.datahub.graphql.generated.CreateDomainInput;
import com.linkedin.datahub.graphql.generated.OwnerEntityType;
import com.linkedin.datahub.graphql.generated.OwnershipType;
import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils;
import com.linkedin.datahub.graphql.resolvers.mutate.util.OwnerUtils;
import com.linkedin.domain.DomainProperties;
import com.linkedin.entity.client.EntityClient;
Expand All @@ -19,8 +23,11 @@
import com.linkedin.mxe.MetadataChangeProposal;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;

import java.net.URISyntaxException;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

Expand All @@ -45,9 +52,9 @@ public CompletableFuture<String> get(DataFetchingEnvironment environment) throws

final QueryContext context = environment.getContext();
final CreateDomainInput input = bindArgument(environment.getArgument("input"), CreateDomainInput.class);
final Urn parentDomain = input.getParentDomain() != null ? UrnUtils.getUrn(input.getParentDomain()) : null;

return CompletableFuture.supplyAsync(() -> {

if (!AuthorizationUtils.canCreateDomains(context)) {
throw new AuthorizationException("Unauthorized to perform this action. Please contact your DataHub administrator.");
}
Expand All @@ -64,6 +71,17 @@ public CompletableFuture<String> get(DataFetchingEnvironment environment) throws
throw new IllegalArgumentException("This Domain already exists!");
}

if (parentDomain != null && !_entityClient.exists(parentDomain, context.getAuthentication())) {
throw new IllegalArgumentException("Parent Domain does not exist!");
}

if (DomainUtils.hasNameConflict(input.getName(), parentDomain, context, _entityClient)) {
throw new DataHubGraphQLException(
String.format("\"%s\" already exists in this domain. Please pick a unique name.", input.getName()),
DataHubGraphQLErrorCode.CONFLICT
);
}

// Create the MCP
final MetadataChangeProposal proposal = buildMetadataChangeProposalWithKey(key, DOMAIN_ENTITY_NAME,
DOMAIN_PROPERTIES_ASPECT_NAME, mapDomainProperties(input, context));
Expand All @@ -77,6 +95,8 @@ public CompletableFuture<String> get(DataFetchingEnvironment environment) throws
}
OwnerUtils.addCreatorAsOwner(context, domainUrn, OwnerEntityType.CORP_USER, ownershipType, _entityService);
return domainUrn;
} catch (DataHubGraphQLException e) {
throw e;
} catch (Exception e) {
log.error("Failed to create Domain with id: {}, name: {}: {}", input.getId(), input.getName(), e.getMessage());
throw new RuntimeException(String.format("Failed to create Domain with id: %s, name: %s", input.getId(), input.getName()), e);
Expand All @@ -89,6 +109,13 @@ private DomainProperties mapDomainProperties(final CreateDomainInput input, fina
result.setName(input.getName());
result.setDescription(input.getDescription(), SetMode.IGNORE_NULL);
result.setCreated(new AuditStamp().setActor(UrnUtils.getUrn(context.getActorUrn())).setTime(System.currentTimeMillis()));
if (input.getParentDomain() != null) {
try {
result.setParentDomain(Urn.createFromString(input.getParentDomain()));
} catch (URISyntaxException e) {
throw new RuntimeException(String.format("Failed to create Domain Urn from string: %s", input.getParentDomain()), e);
}
}
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.linkedin.datahub.graphql.QueryContext;
import com.linkedin.datahub.graphql.authorization.AuthorizationUtils;
import com.linkedin.datahub.graphql.exception.AuthorizationException;
import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils;
import com.linkedin.entity.client.EntityClient;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
Expand Down Expand Up @@ -32,6 +33,11 @@ public CompletableFuture<Boolean> get(final DataFetchingEnvironment environment)

if (AuthorizationUtils.canManageDomains(context) || AuthorizationUtils.canDeleteEntity(urn, context)) {
try {
// Make sure there are no child domains
if (DomainUtils.hasChildDomains(urn, context, _entityClient)) {
throw new RuntimeException(String.format("Cannot delete domain %s which has child domains", domainUrn));
}

_entityClient.deleteEntity(urn, context.getAuthentication());
log.info(String.format("I've successfully deleted the entity %s with urn", domainUrn));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.linkedin.datahub.graphql.resolvers.domain;

import com.google.common.collect.ImmutableList;
import com.linkedin.datahub.graphql.QueryContext;
import com.linkedin.datahub.graphql.generated.Domain;
import com.linkedin.datahub.graphql.generated.DomainEntitiesInput;
Expand Down Expand Up @@ -67,17 +66,22 @@ public CompletableFuture<SearchResults> get(final DataFetchingEnvironment enviro

try {

final CriterionArray criteria = new CriterionArray();
final Criterion filterCriterion = new Criterion()
.setField(DOMAINS_FIELD_NAME + ".keyword")
.setCondition(Condition.EQUAL)
.setValue(urn);
criteria.add(filterCriterion);
if (input.getFilters() != null) {
input.getFilters().forEach(filter -> {
criteria.add(new Criterion().setField(filter.getField()).setValue(filter.getValue()));
});
}

return UrnSearchResultsMapper.map(_entityClient.searchAcrossEntities(
SEARCHABLE_ENTITY_TYPES.stream().map(EntityTypeMapper::getName).collect(Collectors.toList()),
query,
new Filter().setOr(new ConjunctiveCriterionArray(
new ConjunctiveCriterion().setAnd(new CriterionArray(ImmutableList.of(filterCriterion)))
)),
new Filter().setOr(new ConjunctiveCriterionArray(new ConjunctiveCriterion().setAnd(criteria))),
start,
count,
null,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
package com.linkedin.datahub.graphql.resolvers.domain;

import com.linkedin.common.urn.Urn;
import com.linkedin.common.urn.UrnUtils;
import com.linkedin.datahub.graphql.QueryContext;
import com.linkedin.datahub.graphql.authorization.AuthorizationUtils;
import com.linkedin.datahub.graphql.exception.AuthorizationException;
import com.linkedin.datahub.graphql.generated.Domain;
import com.linkedin.datahub.graphql.generated.EntityType;
import com.linkedin.datahub.graphql.generated.ListDomainsInput;
import com.linkedin.datahub.graphql.generated.ListDomainsResult;
import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils;
import com.linkedin.entity.client.EntityClient;
import com.linkedin.metadata.Constants;
import com.linkedin.metadata.query.SearchFlags;
import com.linkedin.metadata.query.filter.Filter;
import com.linkedin.metadata.query.filter.SortCriterion;
import com.linkedin.metadata.query.filter.SortOrder;
import com.linkedin.metadata.search.SearchEntity;
import com.linkedin.metadata.search.SearchResult;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
Expand All @@ -30,7 +32,6 @@
* Resolver used for listing all Domains defined within DataHub. Requires the MANAGE_DOMAINS platform privilege.
*/
public class ListDomainsResolver implements DataFetcher<CompletableFuture<ListDomainsResult>> {

private static final Integer DEFAULT_START = 0;
private static final Integer DEFAULT_COUNT = 20;
private static final String DEFAULT_QUERY = "";
Expand All @@ -48,18 +49,19 @@ public CompletableFuture<ListDomainsResult> get(final DataFetchingEnvironment en

return CompletableFuture.supplyAsync(() -> {

if (AuthorizationUtils.canCreateDomains(context)) {
final ListDomainsInput input = bindArgument(environment.getArgument("input"), ListDomainsInput.class);
final Integer start = input.getStart() == null ? DEFAULT_START : input.getStart();
final Integer count = input.getCount() == null ? DEFAULT_COUNT : input.getCount();
final String query = input.getQuery() == null ? DEFAULT_QUERY : input.getQuery();
final Urn parentDomainUrn = input.getParentDomain() != null ? UrnUtils.getUrn(input.getParentDomain()) : null;
final Filter filter = DomainUtils.buildParentDomainFilter(parentDomainUrn);

try {
// First, get all group Urns.
// First, get all domain Urns.
final SearchResult gmsResult = _entityClient.search(
Constants.DOMAIN_ENTITY_NAME,
query,
null,
filter,
new SortCriterion().setField(DOMAIN_CREATED_TIME_INDEX_FIELD_NAME).setOrder(SortOrder.DESCENDING),
start,
count,
Expand All @@ -78,8 +80,6 @@ public CompletableFuture<ListDomainsResult> get(final DataFetchingEnvironment en
} catch (Exception e) {
throw new RuntimeException("Failed to list domains", e);
}
}
throw new AuthorizationException("Unauthorized to perform this action. Please contact your DataHub administrator.");
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.linkedin.datahub.graphql.resolvers.domain;

import com.linkedin.common.urn.Urn;
import com.linkedin.common.urn.UrnUtils;
import com.linkedin.datahub.graphql.QueryContext;
import com.linkedin.datahub.graphql.generated.Entity;
import com.linkedin.datahub.graphql.generated.ParentDomainsResult;
import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils;
import com.linkedin.entity.client.EntityClient;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

import static com.linkedin.metadata.Constants.DOMAIN_ENTITY_NAME;

public class ParentDomainsResolver implements DataFetcher<CompletableFuture<ParentDomainsResult>> {

private final EntityClient _entityClient;

public ParentDomainsResolver(final EntityClient entityClient) {
_entityClient = entityClient;
}

@Override
public CompletableFuture<ParentDomainsResult> get(DataFetchingEnvironment environment) {
final QueryContext context = environment.getContext();
final Urn urn = UrnUtils.getUrn(((Entity) environment.getSource()).getUrn());
final List<Entity> parentDomains = new ArrayList<>();
final Set<String> visitedParentUrns = new HashSet<>();

if (!DOMAIN_ENTITY_NAME.equals(urn.getEntityType())) {
throw new IllegalArgumentException(String.format("Failed to resolve parents for entity type %s", urn));
}

return CompletableFuture.supplyAsync(() -> {
try {
Entity parentDomain = DomainUtils.getParentDomain(urn, context, _entityClient);

while (parentDomain != null && !visitedParentUrns.contains(parentDomain.getUrn())) {
parentDomains.add(parentDomain);
visitedParentUrns.add(parentDomain.getUrn());
parentDomain = DomainUtils.getParentDomain(Urn.createFromString(parentDomain.getUrn()), context, _entityClient);
}

final ParentDomainsResult result = new ParentDomainsResult();
result.setCount(parentDomains.size());
result.setDomains(parentDomains);
return result;
} catch (Exception e) {
throw new RuntimeException(String.format("Failed to load parent domains for entity %s", urn), e);
}
});
}
}
Loading

0 comments on commit 3e63527

Please sign in to comment.