Fix #2435: Add tagging support for services and database (#9330)

* Fix #2435: Add tagging support for services and database

* Fix check style

* Fix check style

* Fix check style
This commit is contained in:
Sriharsha Chintalapani 2022-12-16 08:34:26 -08:00 committed by GitHub
parent 08f6536558
commit 0055ca2d1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 319 additions and 21 deletions

View File

@ -24,6 +24,7 @@ import org.openmetadata.schema.entity.data.Database;
import org.openmetadata.schema.entity.services.DatabaseService; import org.openmetadata.schema.entity.services.DatabaseService;
import org.openmetadata.schema.type.EntityReference; import org.openmetadata.schema.type.EntityReference;
import org.openmetadata.schema.type.Relationship; import org.openmetadata.schema.type.Relationship;
import org.openmetadata.schema.type.TagLabel;
import org.openmetadata.service.Entity; import org.openmetadata.service.Entity;
import org.openmetadata.service.exception.CatalogExceptionMessage; import org.openmetadata.service.exception.CatalogExceptionMessage;
import org.openmetadata.service.jdbi3.CollectionDAO.EntityRelationshipRecord; import org.openmetadata.service.jdbi3.CollectionDAO.EntityRelationshipRecord;
@ -33,7 +34,7 @@ import org.openmetadata.service.util.EntityUtil.Fields;
import org.openmetadata.service.util.FullyQualifiedName; import org.openmetadata.service.util.FullyQualifiedName;
public class DatabaseRepository extends EntityRepository<Database> { public class DatabaseRepository extends EntityRepository<Database> {
private static final String DATABASE_UPDATE_FIELDS = "owner"; private static final String DATABASE_UPDATE_FIELDS = "owner,tags";
private static final String DATABASE_PATCH_FIELDS = DATABASE_UPDATE_FIELDS; private static final String DATABASE_PATCH_FIELDS = DATABASE_UPDATE_FIELDS;
public DatabaseRepository(CollectionDAO dao) { public DatabaseRepository(CollectionDAO dao) {
@ -67,14 +68,14 @@ public class DatabaseRepository extends EntityRepository<Database> {
// Relationships and fields such as href are derived and not stored as part of json // Relationships and fields such as href are derived and not stored as part of json
EntityReference owner = database.getOwner(); EntityReference owner = database.getOwner();
EntityReference service = database.getService(); EntityReference service = database.getService();
List<TagLabel> tags = database.getTags();
// Don't store owner, database, href and tags as JSON. Build it on the fly based on relationships // Don't store owner, database, href and tags as JSON. Build it on the fly based on relationships
database.withOwner(null).withService(null).withHref(null); database.withOwner(null).withService(null).withHref(null).withTags(null);
store(database, update); store(database, update);
// Restore the relationships // Restore the relationships
database.withOwner(owner).withService(service); database.withOwner(owner).withService(service).withTags(tags);
} }
@Override @Override
@ -82,6 +83,8 @@ public class DatabaseRepository extends EntityRepository<Database> {
EntityReference service = database.getService(); EntityReference service = database.getService();
addRelationship(service.getId(), database.getId(), service.getType(), Entity.DATABASE, Relationship.CONTAINS); addRelationship(service.getId(), database.getId(), service.getType(), Entity.DATABASE, Relationship.CONTAINS);
storeOwner(database, database.getOwner()); storeOwner(database, database.getOwner());
// Add tag to database relationship
applyTags(database);
} }
private List<EntityReference> getSchemas(Database database) throws IOException { private List<EntityReference> getSchemas(Database database) throws IOException {

View File

@ -16,11 +16,13 @@ import static org.openmetadata.service.Entity.FIELD_OWNER;
import static org.openmetadata.service.util.EntityUtil.objectMatch; import static org.openmetadata.service.util.EntityUtil.objectMatch;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import lombok.Getter; import lombok.Getter;
import org.openmetadata.schema.ServiceConnectionEntityInterface; import org.openmetadata.schema.ServiceConnectionEntityInterface;
import org.openmetadata.schema.ServiceEntityInterface; import org.openmetadata.schema.ServiceEntityInterface;
import org.openmetadata.schema.entity.services.ServiceType; import org.openmetadata.schema.entity.services.ServiceType;
import org.openmetadata.schema.type.EntityReference; import org.openmetadata.schema.type.EntityReference;
import org.openmetadata.schema.type.TagLabel;
import org.openmetadata.service.secrets.SecretsManager; import org.openmetadata.service.secrets.SecretsManager;
import org.openmetadata.service.secrets.SecretsManagerFactory; import org.openmetadata.service.secrets.SecretsManagerFactory;
import org.openmetadata.service.util.EntityUtil; import org.openmetadata.service.util.EntityUtil;
@ -29,7 +31,8 @@ import org.openmetadata.service.util.JsonUtils;
public abstract class ServiceEntityRepository< public abstract class ServiceEntityRepository<
T extends ServiceEntityInterface, S extends ServiceConnectionEntityInterface> T extends ServiceEntityInterface, S extends ServiceConnectionEntityInterface>
extends EntityRepository<T> { extends EntityRepository<T> {
private static final String UPDATE_FIELDS = "owner"; private static final String UPDATE_FIELDS = "owner,tags";
private static final String PATCH_FIELDS = UPDATE_FIELDS;
@Getter private final Class<S> serviceConnectionClass; @Getter private final Class<S> serviceConnectionClass;
@ -53,7 +56,7 @@ public abstract class ServiceEntityRepository<
Class<S> serviceConnectionClass, Class<S> serviceConnectionClass,
String updatedFields, String updatedFields,
ServiceType serviceType) { ServiceType serviceType) {
super(collectionPath, service, entityDAO.getEntityClass(), entityDAO, dao, "", updatedFields); super(collectionPath, service, entityDAO.getEntityClass(), entityDAO, dao, PATCH_FIELDS, updatedFields);
this.serviceConnectionClass = serviceConnectionClass; this.serviceConnectionClass = serviceConnectionClass;
this.serviceType = serviceType; this.serviceType = serviceType;
} }
@ -74,9 +77,9 @@ public abstract class ServiceEntityRepository<
public void storeEntity(T service, boolean update) throws IOException { public void storeEntity(T service, boolean update) throws IOException {
// Relationships and fields such as href are derived and not stored as part of json // Relationships and fields such as href are derived and not stored as part of json
EntityReference owner = service.getOwner(); EntityReference owner = service.getOwner();
List<TagLabel> tags = service.getTags();
// Don't store owner, service, href and tags as JSON. Build it on the fly based on relationships // Don't store owner, service, href and tags as JSON. Build it on the fly based on relationships
service.withOwner(null).withHref(null); service.withOwner(null).withHref(null).setTags(null);
service service
.getConnection() .getConnection()
@ -92,13 +95,15 @@ public abstract class ServiceEntityRepository<
store(service, update); store(service, update);
// Restore the relationships // Restore the relationships
service.withOwner(owner); service.withOwner(owner).setTags(tags);
} }
@Override @Override
public void storeRelationships(T service) { public void storeRelationships(T service) {
// Add owner relationship // Add owner relationship
storeOwner(service, service.getOwner()); storeOwner(service, service.getOwner());
// add tags relationship
applyTags(service);
} }
@Override @Override

View File

@ -85,7 +85,7 @@ public class DatabaseResource extends EntityResource<Database, DatabaseRepositor
DatabaseList() {} DatabaseList() {}
} }
static final String FIELDS = "owner,databaseSchemas,usageSummary,location"; static final String FIELDS = "owner,databaseSchemas,usageSummary,location,tags";
@GET @GET
@Operation( @Operation(

View File

@ -16,15 +16,19 @@ package org.openmetadata.service.resources.services.dashboard;
import static org.openmetadata.service.Entity.FIELD_OWNER; import static org.openmetadata.service.Entity.FIELD_OWNER;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponse;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.json.JsonPatch;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.Max; import javax.validation.constraints.Max;
import javax.validation.constraints.Min; import javax.validation.constraints.Min;
@ -32,6 +36,7 @@ import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue; import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.PATCH;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
@ -317,6 +322,32 @@ public class DashboardServiceResource
return response; return response;
} }
@PATCH
@Path("/{id}")
@Operation(
operationId = "patchDashboardService",
summary = "Update a dashboard service",
tags = "dashboardServices",
description = "Update an existing dashboard service using JsonPatch.",
externalDocs = @ExternalDocumentation(description = "JsonPatch RFC", url = "https://tools.ietf.org/html/rfc6902"))
@Consumes(MediaType.APPLICATION_JSON_PATCH_JSON)
public Response patch(
@Context UriInfo uriInfo,
@Context SecurityContext securityContext,
@PathParam("id") UUID id,
@RequestBody(
description = "JsonPatch with array of operations",
content =
@Content(
mediaType = MediaType.APPLICATION_JSON_PATCH_JSON,
examples = {
@ExampleObject("[" + "{op:remove, path:/a}," + "{op:add, path: /b, value: val}" + "]")
}))
JsonPatch patch)
throws IOException {
return patchInternal(uriInfo, securityContext, id, patch);
}
@DELETE @DELETE
@Path("/{id}") @Path("/{id}")
@Operation( @Operation(

View File

@ -14,15 +14,19 @@
package org.openmetadata.service.resources.services.database; package org.openmetadata.service.resources.services.database;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponse;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.json.JsonPatch;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.Max; import javax.validation.constraints.Max;
import javax.validation.constraints.Min; import javax.validation.constraints.Min;
@ -30,6 +34,7 @@ import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue; import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.PATCH;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
@ -70,7 +75,7 @@ import org.openmetadata.service.util.ResultList;
public class DatabaseServiceResource public class DatabaseServiceResource
extends ServiceEntityResource<DatabaseService, DatabaseServiceRepository, DatabaseConnection> { extends ServiceEntityResource<DatabaseService, DatabaseServiceRepository, DatabaseConnection> {
public static final String COLLECTION_PATH = "v1/services/databaseServices/"; public static final String COLLECTION_PATH = "v1/services/databaseServices/";
static final String FIELDS = "pipelines,owner"; static final String FIELDS = "pipelines,owner,tags";
@Override @Override
public DatabaseService addHref(UriInfo uriInfo, DatabaseService service) { public DatabaseService addHref(UriInfo uriInfo, DatabaseService service) {
@ -322,6 +327,32 @@ public class DatabaseServiceResource
return response; return response;
} }
@PATCH
@Path("/{id}")
@Operation(
operationId = "patchDatabaseService",
summary = "Update a database service",
tags = "databaseServices",
description = "Update an existing database service using JsonPatch.",
externalDocs = @ExternalDocumentation(description = "JsonPatch RFC", url = "https://tools.ietf.org/html/rfc6902"))
@Consumes(MediaType.APPLICATION_JSON_PATCH_JSON)
public Response patch(
@Context UriInfo uriInfo,
@Context SecurityContext securityContext,
@PathParam("id") UUID id,
@RequestBody(
description = "JsonPatch with array of operations",
content =
@Content(
mediaType = MediaType.APPLICATION_JSON_PATCH_JSON,
examples = {
@ExampleObject("[" + "{op:remove, path:/a}," + "{op:add, path: /b, value: val}" + "]")
}))
JsonPatch patch)
throws IOException {
return patchInternal(uriInfo, securityContext, id, patch);
}
@DELETE @DELETE
@Path("/{id}") @Path("/{id}")
@Operation( @Operation(

View File

@ -16,15 +16,19 @@ package org.openmetadata.service.resources.services.messaging;
import static org.openmetadata.service.Entity.FIELD_OWNER; import static org.openmetadata.service.Entity.FIELD_OWNER;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponse;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.json.JsonPatch;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.Max; import javax.validation.constraints.Max;
import javax.validation.constraints.Min; import javax.validation.constraints.Min;
@ -32,6 +36,7 @@ import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue; import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.PATCH;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
@ -319,6 +324,32 @@ public class MessagingServiceResource
return response; return response;
} }
@PATCH
@Path("/{id}")
@Operation(
operationId = "patchMessagingService",
summary = "Update a Messaging Service",
tags = "messagingServices",
description = "Update an existing messaging service using JsonPatch.",
externalDocs = @ExternalDocumentation(description = "JsonPatch RFC", url = "https://tools.ietf.org/html/rfc6902"))
@Consumes(MediaType.APPLICATION_JSON_PATCH_JSON)
public Response patch(
@Context UriInfo uriInfo,
@Context SecurityContext securityContext,
@PathParam("id") UUID id,
@RequestBody(
description = "JsonPatch with array of operations",
content =
@Content(
mediaType = MediaType.APPLICATION_JSON_PATCH_JSON,
examples = {
@ExampleObject("[" + "{op:remove, path:/a}," + "{op:add, path: /b, value: val}" + "]")
}))
JsonPatch patch)
throws IOException {
return patchInternal(uriInfo, securityContext, id, patch);
}
@DELETE @DELETE
@Path("/{id}") @Path("/{id}")
@Operation( @Operation(

View File

@ -1,16 +1,20 @@
package org.openmetadata.service.resources.services.metadata; package org.openmetadata.service.resources.services.metadata;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponse;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.json.JsonPatch;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.Max; import javax.validation.constraints.Max;
import javax.validation.constraints.Min; import javax.validation.constraints.Min;
@ -18,6 +22,7 @@ import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue; import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.PATCH;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
@ -65,7 +70,7 @@ import org.openmetadata.service.util.ResultList;
public class MetadataServiceResource public class MetadataServiceResource
extends ServiceEntityResource<MetadataService, MetadataServiceRepository, MetadataConnection> { extends ServiceEntityResource<MetadataService, MetadataServiceRepository, MetadataConnection> {
public static final String COLLECTION_PATH = "v1/services/metadataServices/"; public static final String COLLECTION_PATH = "v1/services/metadataServices/";
public static final String FIELDS = "pipelines,owner"; public static final String FIELDS = "pipelines,owner,tags";
public void initialize(OpenMetadataApplicationConfig config) throws IOException { public void initialize(OpenMetadataApplicationConfig config) throws IOException {
registerMetadataServices(config); registerMetadataServices(config);
@ -352,6 +357,32 @@ public class MetadataServiceResource
return response; return response;
} }
@PATCH
@Path("/{id}")
@Operation(
operationId = "patchMetadataService",
summary = "Update a Metadata service",
tags = "metadataService",
description = "Update an existing Metadata service using JsonPatch.",
externalDocs = @ExternalDocumentation(description = "JsonPatch RFC", url = "https://tools.ietf.org/html/rfc6902"))
@Consumes(MediaType.APPLICATION_JSON_PATCH_JSON)
public Response patch(
@Context UriInfo uriInfo,
@Context SecurityContext securityContext,
@PathParam("id") UUID id,
@RequestBody(
description = "JsonPatch with array of operations",
content =
@Content(
mediaType = MediaType.APPLICATION_JSON_PATCH_JSON,
examples = {
@ExampleObject("[" + "{op:remove, path:/a}," + "{op:add, path: /b, value: val}" + "]")
}))
JsonPatch patch)
throws IOException {
return patchInternal(uriInfo, securityContext, id, patch);
}
@DELETE @DELETE
@Path("/{id}") @Path("/{id}")
@Operation( @Operation(

View File

@ -14,15 +14,19 @@
package org.openmetadata.service.resources.services.mlmodel; package org.openmetadata.service.resources.services.mlmodel;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponse;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.json.JsonPatch;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.Max; import javax.validation.constraints.Max;
import javax.validation.constraints.Min; import javax.validation.constraints.Min;
@ -30,6 +34,7 @@ import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue; import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.PATCH;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
@ -68,7 +73,7 @@ public class MlModelServiceResource
extends ServiceEntityResource<MlModelService, MlModelServiceRepository, MlModelConnection> { extends ServiceEntityResource<MlModelService, MlModelServiceRepository, MlModelConnection> {
public static final String COLLECTION_PATH = "v1/services/mlmodelServices/"; public static final String COLLECTION_PATH = "v1/services/mlmodelServices/";
public static final String FIELDS = "pipelines,owner"; public static final String FIELDS = "pipelines,owner,tags";
@Override @Override
public MlModelService addHref(UriInfo uriInfo, MlModelService service) { public MlModelService addHref(UriInfo uriInfo, MlModelService service) {
@ -318,6 +323,32 @@ public class MlModelServiceResource
return response; return response;
} }
@PATCH
@Path("/{id}")
@Operation(
operationId = "patchMlModelService",
summary = "Update a MlModel service",
tags = "mlModelServices",
description = "Update an existing MlModelService service using JsonPatch.",
externalDocs = @ExternalDocumentation(description = "JsonPatch RFC", url = "https://tools.ietf.org/html/rfc6902"))
@Consumes(MediaType.APPLICATION_JSON_PATCH_JSON)
public Response patch(
@Context UriInfo uriInfo,
@Context SecurityContext securityContext,
@PathParam("id") UUID id,
@RequestBody(
description = "JsonPatch with array of operations",
content =
@Content(
mediaType = MediaType.APPLICATION_JSON_PATCH_JSON,
examples = {
@ExampleObject("[" + "{op:remove, path:/a}," + "{op:add, path: /b, value: val}" + "]")
}))
JsonPatch patch)
throws IOException {
return patchInternal(uriInfo, securityContext, id, patch);
}
@DELETE @DELETE
@Path("/{id}") @Path("/{id}")
@Operation( @Operation(

View File

@ -14,15 +14,19 @@
package org.openmetadata.service.resources.services.pipeline; package org.openmetadata.service.resources.services.pipeline;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponse;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.json.JsonPatch;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.Max; import javax.validation.constraints.Max;
import javax.validation.constraints.Min; import javax.validation.constraints.Min;
@ -30,6 +34,7 @@ import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue; import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.PATCH;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
@ -317,6 +322,32 @@ public class PipelineServiceResource
return response; return response;
} }
@PATCH
@Path("/{id}")
@Operation(
operationId = "patchPipelineService",
summary = "Update a Pipeline Service",
tags = "pipelineServices",
description = "Update an existing pipeline service using JsonPatch.",
externalDocs = @ExternalDocumentation(description = "JsonPatch RFC", url = "https://tools.ietf.org/html/rfc6902"))
@Consumes(MediaType.APPLICATION_JSON_PATCH_JSON)
public Response patch(
@Context UriInfo uriInfo,
@Context SecurityContext securityContext,
@PathParam("id") UUID id,
@RequestBody(
description = "JsonPatch with array of operations",
content =
@Content(
mediaType = MediaType.APPLICATION_JSON_PATCH_JSON,
examples = {
@ExampleObject("[" + "{op:remove, path:/a}," + "{op:add, path: /b, value: val}" + "]")
}))
JsonPatch patch)
throws IOException {
return patchInternal(uriInfo, securityContext, id, patch);
}
@DELETE @DELETE
@Path("/{id}") @Path("/{id}")
@Operation( @Operation(

View File

@ -125,7 +125,7 @@ public class DatabaseResourceTest extends EntityResourceTest<Database, CreateDat
assertListNull( assertListNull(
database.getOwner(), database.getDatabaseSchemas(), database.getUsageSummary(), database.getLocation()); database.getOwner(), database.getDatabaseSchemas(), database.getUsageSummary(), database.getLocation());
fields = "owner,databaseSchemas,usageSummary,location"; fields = "owner,databaseSchemas,usageSummary,location,tags";
database = database =
byName byName
? getEntityByName(database.getFullyQualifiedName(), fields, ADMIN_AUTH_HEADERS) ? getEntityByName(database.getFullyQualifiedName(), fields, ADMIN_AUTH_HEADERS)

View File

@ -217,7 +217,7 @@ public class DashboardServiceResourceTest extends EntityResourceTest<DashboardSe
: getEntity(service.getId(), fields, ADMIN_AUTH_HEADERS); : getEntity(service.getId(), fields, ADMIN_AUTH_HEADERS);
TestUtils.assertListNull(service.getOwner()); TestUtils.assertListNull(service.getOwner());
fields = "owner"; fields = "owner,tags";
service = service =
byName byName
? getEntityByName(service.getFullyQualifiedName(), fields, ADMIN_AUTH_HEADERS) ? getEntityByName(service.getFullyQualifiedName(), fields, ADMIN_AUTH_HEADERS)

View File

@ -66,7 +66,7 @@ public class DatabaseServiceResourceTest extends EntityResourceTest<DatabaseServ
DatabaseService.class, DatabaseService.class,
DatabaseServiceList.class, DatabaseServiceList.class,
"services/databaseServices", "services/databaseServices",
"owner"); "owner,tags");
this.supportsPatch = false; this.supportsPatch = false;
this.supportsAuthorizedMetadataOperations = false; this.supportsAuthorizedMetadataOperations = false;
} }
@ -288,7 +288,7 @@ public class DatabaseServiceResourceTest extends EntityResourceTest<DatabaseServ
: getEntity(service.getId(), fields, ADMIN_AUTH_HEADERS); : getEntity(service.getId(), fields, ADMIN_AUTH_HEADERS);
TestUtils.assertListNull(service.getOwner()); TestUtils.assertListNull(service.getOwner());
fields = "owner"; fields = "owner,tags";
service = service =
byName byName
? getEntityByName(service.getFullyQualifiedName(), fields, ADMIN_AUTH_HEADERS) ? getEntityByName(service.getFullyQualifiedName(), fields, ADMIN_AUTH_HEADERS)

View File

@ -208,7 +208,7 @@ public class MessagingServiceResourceTest extends EntityResourceTest<MessagingSe
: getEntity(service.getId(), fields, ADMIN_AUTH_HEADERS); : getEntity(service.getId(), fields, ADMIN_AUTH_HEADERS);
TestUtils.assertListNull(service.getOwner()); TestUtils.assertListNull(service.getOwner());
fields = "owner"; fields = "owner,tags";
service = service =
byName byName
? getEntityByName(service.getFullyQualifiedName(), null, fields, ADMIN_AUTH_HEADERS) ? getEntityByName(service.getFullyQualifiedName(), null, fields, ADMIN_AUTH_HEADERS)

View File

@ -197,7 +197,7 @@ public class MetadataServiceResourceTest extends EntityResourceTest<MetadataServ
: getEntity(service.getId(), fields, ADMIN_AUTH_HEADERS); : getEntity(service.getId(), fields, ADMIN_AUTH_HEADERS);
TestUtils.assertListNull(service.getOwner()); TestUtils.assertListNull(service.getOwner());
fields = "owner"; fields = "owner,tags";
service = service =
byName byName
? getEntityByName(service.getFullyQualifiedName(), null, fields, ADMIN_AUTH_HEADERS) ? getEntityByName(service.getFullyQualifiedName(), null, fields, ADMIN_AUTH_HEADERS)

View File

@ -156,7 +156,7 @@ public class MlModelServiceResourceTest extends EntityResourceTest<MlModelServic
: getEntity(service.getId(), fields, ADMIN_AUTH_HEADERS); : getEntity(service.getId(), fields, ADMIN_AUTH_HEADERS);
TestUtils.assertListNull(service.getOwner()); TestUtils.assertListNull(service.getOwner());
fields = "owner"; fields = "owner,tags";
service = service =
byName byName
? getEntityByName(service.getFullyQualifiedName(), fields, ADMIN_AUTH_HEADERS) ? getEntityByName(service.getFullyQualifiedName(), fields, ADMIN_AUTH_HEADERS)

View File

@ -222,7 +222,7 @@ public class PipelineServiceResourceTest extends EntityResourceTest<PipelineServ
: getEntity(service.getId(), fields, ADMIN_AUTH_HEADERS); : getEntity(service.getId(), fields, ADMIN_AUTH_HEADERS);
TestUtils.assertListNull(service.getOwner()); TestUtils.assertListNull(service.getOwner());
fields = "owner"; fields = "owner,tags";
service = service =
byName byName
? getEntityByName(service.getFullyQualifiedName(), fields, ADMIN_AUTH_HEADERS) ? getEntityByName(service.getFullyQualifiedName(), fields, ADMIN_AUTH_HEADERS)

View File

@ -20,6 +20,14 @@
"description": "Description of the database instance. What it has and how to use it.", "description": "Description of the database instance. What it has and how to use it.",
"$ref": "../../type/basic.json#/definitions/markdown" "$ref": "../../type/basic.json#/definitions/markdown"
}, },
"tags": {
"description": "Tags for this Database Service.",
"type": "array",
"items": {
"$ref": "../../type/tagLabel.json"
},
"default": null
},
"owner": { "owner": {
"description": "Owner of this database", "description": "Owner of this database",
"$ref": "../../type/entityReference.json" "$ref": "../../type/entityReference.json"

View File

@ -26,6 +26,14 @@
"connection": { "connection": {
"$ref": "../../entity/services/dashboardService.json#/definitions/dashboardConnection" "$ref": "../../entity/services/dashboardService.json#/definitions/dashboardConnection"
}, },
"tags": {
"description": "Tags for this Dashboard Service.",
"type": "array",
"items": {
"$ref": "../../type/tagLabel.json"
},
"default": null
},
"owner": { "owner": {
"description": "Owner of this dashboard service.", "description": "Owner of this dashboard service.",
"$ref": "../../type/entityReference.json" "$ref": "../../type/entityReference.json"

View File

@ -20,6 +20,14 @@
"description": "Description of Database entity.", "description": "Description of Database entity.",
"$ref": "../../type/basic.json#/definitions/markdown" "$ref": "../../type/basic.json#/definitions/markdown"
}, },
"tags": {
"description": "Tags for this Database Service.",
"type": "array",
"items": {
"$ref": "../../type/tagLabel.json"
},
"default": null
},
"serviceType": { "serviceType": {
"$ref": "../../entity/services/databaseService.json#/definitions/databaseServiceType" "$ref": "../../entity/services/databaseService.json#/definitions/databaseServiceType"
}, },

View File

@ -26,6 +26,14 @@
"connection": { "connection": {
"$ref": "../../entity/services/messagingService.json#/definitions/messagingConnection" "$ref": "../../entity/services/messagingService.json#/definitions/messagingConnection"
}, },
"tags": {
"description": "Tags for this Messaging Service.",
"type": "array",
"items": {
"$ref": "../../type/tagLabel.json"
},
"default": null
},
"owner": { "owner": {
"description": "Owner of this messaging service.", "description": "Owner of this messaging service.",
"$ref": "../../type/entityReference.json" "$ref": "../../type/entityReference.json"

View File

@ -26,6 +26,14 @@
"connection": { "connection": {
"$ref": "../../entity/services/mlmodelService.json#/definitions/mlModelConnection" "$ref": "../../entity/services/mlmodelService.json#/definitions/mlModelConnection"
}, },
"tags": {
"description": "Tags for this MlModel Service.",
"type": "array",
"items": {
"$ref": "../../type/tagLabel.json"
},
"default": null
},
"owner": { "owner": {
"description": "Owner of this mlModel service.", "description": "Owner of this mlModel service.",
"$ref": "../../type/entityReference.json" "$ref": "../../type/entityReference.json"

View File

@ -26,6 +26,14 @@
"connection": { "connection": {
"$ref": "../../entity/services/pipelineService.json#/definitions/pipelineConnection" "$ref": "../../entity/services/pipelineService.json#/definitions/pipelineConnection"
}, },
"tags": {
"description": "Tags for this Pipeline Service.",
"type": "array",
"items": {
"$ref": "../../type/tagLabel.json"
},
"default": null
},
"owner": { "owner": {
"description": "Owner of this pipeline service.", "description": "Owner of this pipeline service.",
"$ref": "../../type/entityReference.json" "$ref": "../../type/entityReference.json"

View File

@ -27,6 +27,14 @@
"description": "Description of the database instance.", "description": "Description of the database instance.",
"$ref": "../../type/basic.json#/definitions/markdown" "$ref": "../../type/basic.json#/definitions/markdown"
}, },
"tags": {
"description": "Tags for this Database.",
"type": "array",
"items": {
"$ref": "../../type/tagLabel.json"
},
"default": null
},
"version": { "version": {
"description": "Metadata version of the entity.", "description": "Metadata version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/entityVersion" "$ref": "../../type/entityHistory.json#/definitions/entityVersion"

View File

@ -138,6 +138,14 @@
"description": "References to pipelines deployed for this dashboard service.", "description": "References to pipelines deployed for this dashboard service.",
"$ref": "../../type/entityReference.json#/definitions/entityReferenceList" "$ref": "../../type/entityReference.json#/definitions/entityReferenceList"
}, },
"tags": {
"description": "Tags for this Dashboard Service.",
"type": "array",
"items": {
"$ref": "../../type/tagLabel.json"
},
"default": null
},
"owner": { "owner": {
"description": "Owner of this dashboard service.", "description": "Owner of this dashboard service.",
"$ref": "../../type/entityReference.json" "$ref": "../../type/entityReference.json"

View File

@ -278,6 +278,14 @@
"description": "References to pipelines deployed for this database service to extract metadata, usage, lineage etc..", "description": "References to pipelines deployed for this database service to extract metadata, usage, lineage etc..",
"$ref": "../../type/entityReference.json#/definitions/entityReferenceList" "$ref": "../../type/entityReference.json#/definitions/entityReferenceList"
}, },
"tags": {
"description": "Tags for this Database Service.",
"type": "array",
"items": {
"$ref": "../../type/tagLabel.json"
},
"default": null
},
"version": { "version": {
"description": "Metadata version of the entity.", "description": "Metadata version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/entityVersion" "$ref": "../../type/entityHistory.json#/definitions/entityVersion"

View File

@ -105,6 +105,14 @@
"description": "References to pipelines deployed for this messaging service to extract topic configs and schemas.", "description": "References to pipelines deployed for this messaging service to extract topic configs and schemas.",
"$ref": "../../type/entityReference.json#/definitions/entityReferenceList" "$ref": "../../type/entityReference.json#/definitions/entityReferenceList"
}, },
"tags": {
"description": "Tags for this Message Service.",
"type": "array",
"items": {
"$ref": "../../type/tagLabel.json"
},
"default": null
},
"version": { "version": {
"description": "Metadata version of the entity.", "description": "Metadata version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/entityVersion" "$ref": "../../type/entityHistory.json#/definitions/entityVersion"

View File

@ -103,6 +103,14 @@
"description": "User who made the update.", "description": "User who made the update.",
"type": "string" "type": "string"
}, },
"tags": {
"description": "Tags for this Metadata Service.",
"type": "array",
"items": {
"$ref": "../../type/tagLabel.json"
},
"default": null
},
"owner": { "owner": {
"description": "Owner of this database service.", "description": "Owner of this database service.",
"$ref": "../../type/entityReference.json" "$ref": "../../type/entityReference.json"

View File

@ -103,6 +103,14 @@
"connection": { "connection": {
"$ref": "#/definitions/mlModelConnection" "$ref": "#/definitions/mlModelConnection"
}, },
"tags": {
"description": "Tags for this MlModel Service.",
"type": "array",
"items": {
"$ref": "../../type/tagLabel.json"
},
"default": null
},
"owner": { "owner": {
"description": "Owner of this pipeline service.", "description": "Owner of this pipeline service.",
"$ref": "../../type/entityReference.json" "$ref": "../../type/entityReference.json"

View File

@ -129,6 +129,14 @@
"description": "User who made the update.", "description": "User who made the update.",
"type": "string" "type": "string"
}, },
"tags": {
"description": "Tags for this Pipeline Service.",
"type": "array",
"items": {
"$ref": "../../type/tagLabel.json"
},
"default": null
},
"pipelines": { "pipelines": {
"description": "References to pipelines deployed for this pipeline service to extract metadata", "description": "References to pipelines deployed for this pipeline service to extract metadata",
"$ref": "../../type/entityReference.json#/definitions/entityReferenceList" "$ref": "../../type/entityReference.json#/definitions/entityReferenceList"