forked from datahub-project/datahub
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(GraphQL): Support for Deleting Domains, Tags via GraphQL API (da…
- Loading branch information
1 parent
a8539ba
commit 1a0b649
Showing
20 changed files
with
615 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
...ore/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/DeleteDomainResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package com.linkedin.datahub.graphql.resolvers.domain; | ||
|
||
import com.linkedin.common.urn.Urn; | ||
import com.linkedin.datahub.graphql.QueryContext; | ||
import com.linkedin.datahub.graphql.authorization.AuthorizationUtils; | ||
import com.linkedin.datahub.graphql.exception.AuthorizationException; | ||
import com.linkedin.entity.client.EntityClient; | ||
import com.linkedin.r2.RemoteInvocationException; | ||
import graphql.schema.DataFetcher; | ||
import graphql.schema.DataFetchingEnvironment; | ||
import java.util.concurrent.CompletableFuture; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
|
||
/** | ||
* Resolver responsible for hard deleting a particular DataHub Corp Group | ||
*/ | ||
@Slf4j | ||
public class DeleteDomainResolver implements DataFetcher<CompletableFuture<Boolean>> { | ||
|
||
private final EntityClient _entityClient; | ||
|
||
public DeleteDomainResolver(final EntityClient entityClient) { | ||
_entityClient = entityClient; | ||
} | ||
|
||
@Override | ||
public CompletableFuture<Boolean> get(final DataFetchingEnvironment environment) throws Exception { | ||
final QueryContext context = environment.getContext(); | ||
final String domainUrn = environment.getArgument("urn"); | ||
final Urn urn = Urn.createFromString(domainUrn); | ||
return CompletableFuture.supplyAsync(() -> { | ||
|
||
if (AuthorizationUtils.canManageDomains(context) || AuthorizationUtils.canDeleteEntity(urn, context)) { | ||
try { | ||
_entityClient.deleteEntity(urn, context.getAuthentication()); | ||
|
||
// Asynchronously Delete all references to the entity (to return quickly) | ||
CompletableFuture.runAsync(() -> { | ||
try { | ||
_entityClient.deleteEntityReferences(urn, context.getAuthentication()); | ||
} catch (RemoteInvocationException e) { | ||
log.error(String.format("Caught exception while attempting to clear all entity references for Domain with urn %s", urn), e); | ||
} | ||
}); | ||
|
||
return true; | ||
} catch (Exception e) { | ||
throw new RuntimeException(String.format("Failed to perform delete against domain with urn %s", domainUrn), e); | ||
} | ||
} | ||
throw new AuthorizationException("Unauthorized to perform this action. Please contact your DataHub administrator."); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
80 changes: 80 additions & 0 deletions
80
...phql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/tag/CreateTagResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package com.linkedin.datahub.graphql.resolvers.tag; | ||
|
||
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.generated.CreateTagInput; | ||
import com.linkedin.events.metadata.ChangeType; | ||
import com.linkedin.metadata.Constants; | ||
import com.linkedin.metadata.entity.EntityService; | ||
import com.linkedin.metadata.key.TagKey; | ||
import com.linkedin.metadata.utils.EntityKeyUtils; | ||
import com.linkedin.metadata.utils.GenericRecordUtils; | ||
import com.linkedin.mxe.MetadataChangeProposal; | ||
import com.linkedin.tag.TagProperties; | ||
import graphql.schema.DataFetcher; | ||
import graphql.schema.DataFetchingEnvironment; | ||
import java.util.UUID; | ||
import java.util.concurrent.CompletableFuture; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
import static com.linkedin.datahub.graphql.authorization.AuthorizationUtils.*; | ||
import static com.linkedin.datahub.graphql.resolvers.ResolverUtils.*; | ||
|
||
/** | ||
* Resolver used for creating a new Tag on DataHub. Requires the CREATE_TAG or MANAGE_TAGS privilege. | ||
*/ | ||
@Slf4j | ||
@RequiredArgsConstructor | ||
public class CreateTagResolver implements DataFetcher<CompletableFuture<String>> { | ||
|
||
private final EntityService _entityService; | ||
|
||
@Override | ||
public CompletableFuture<String> get(DataFetchingEnvironment environment) throws Exception { | ||
|
||
final QueryContext context = environment.getContext(); | ||
final CreateTagInput input = bindArgument(environment.getArgument("input"), CreateTagInput.class); | ||
|
||
return CompletableFuture.supplyAsync(() -> { | ||
|
||
if (!AuthorizationUtils.canCreateTags(context)) { | ||
throw new AuthorizationException("Unauthorized to perform this action. Please contact your DataHub administrator."); | ||
} | ||
|
||
try { | ||
// Create the Tag Key | ||
final TagKey key = new TagKey(); | ||
|
||
// Take user provided id OR generate a random UUID for the Tag. | ||
final String id = input.getId() != null ? input.getId() : UUID.randomUUID().toString(); | ||
key.setName(id); | ||
|
||
if (_entityService.exists(EntityKeyUtils.convertEntityKeyToUrn(key, Constants.TAG_ENTITY_NAME))) { | ||
throw new IllegalArgumentException("This Tag already exists!"); | ||
} | ||
|
||
// Create the MCP | ||
final MetadataChangeProposal proposal = new MetadataChangeProposal(); | ||
proposal.setEntityKeyAspect(GenericRecordUtils.serializeAspect(key)); | ||
proposal.setEntityType(Constants.TAG_ENTITY_NAME); | ||
proposal.setAspectName(Constants.TAG_PROPERTIES_ASPECT_NAME); | ||
proposal.setAspect(GenericRecordUtils.serializeAspect(mapTagProperties(input))); | ||
proposal.setChangeType(ChangeType.UPSERT); | ||
return _entityService.ingestProposal(proposal, createAuditStamp(context)).getUrn().toString(); | ||
} 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); | ||
} | ||
}); | ||
} | ||
|
||
private TagProperties mapTagProperties(final CreateTagInput input) { | ||
final TagProperties result = new TagProperties(); | ||
result.setName(input.getName()); | ||
result.setDescription(input.getDescription(), SetMode.IGNORE_NULL); | ||
return result; | ||
} | ||
} |
Oops, something went wrong.