mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-07-04 15:45:42 +00:00
12142.task2 - Add domain and data product properties to entities (#12255)
This commit is contained in:
parent
a8396092d8
commit
97140e13fd
@ -9,3 +9,15 @@ CREATE TABLE IF NOT EXISTS domain_entity (
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (fqnHash)
|
||||
);
|
||||
|
||||
-- create data product entity table
|
||||
CREATE TABLE IF NOT EXISTS data_product_entity (
|
||||
id VARCHAR(36) GENERATED ALWAYS AS (json ->> '$.id') STORED NOT NULL,
|
||||
name VARCHAR(256) GENERATED ALWAYS AS (json ->> '$.name') NOT NULL,
|
||||
fqnHash VARCHAR(256) NOT NULL,
|
||||
json JSON NOT NULL,
|
||||
updatedAt BIGINT UNSIGNED GENERATED ALWAYS AS (json ->> '$.updatedAt') NOT NULL,
|
||||
updatedBy VARCHAR(256) GENERATED ALWAYS AS (json ->> '$.updatedBy') NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (fqnHash)
|
||||
);
|
||||
|
@ -9,3 +9,15 @@ CREATE TABLE IF NOT EXISTS domain_entity (
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (fqnHash)
|
||||
);
|
||||
|
||||
-- create data product entity table
|
||||
CREATE TABLE IF NOT EXISTS data_product_entity (
|
||||
id VARCHAR(36) GENERATED ALWAYS AS (json ->> 'id') STORED NOT NULL,
|
||||
name VARCHAR(256) GENERATED ALWAYS AS (json ->> 'name') STORED NOT NULL,
|
||||
fqnHash VARCHAR(256) NOT NULL,
|
||||
json JSONB NOT NULL,
|
||||
updatedAt BIGINT GENERATED ALWAYS AS ((json ->> 'updatedAt')::bigint) STORED NOT NULL,
|
||||
updatedBy VARCHAR(256) GENERATED ALWAYS AS (json ->> 'updatedBy') STORED NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (fqnHash)
|
||||
);
|
||||
|
@ -64,6 +64,8 @@ public final class Entity {
|
||||
public static final String FIELD_DISPLAY_NAME = "displayName";
|
||||
public static final String FIELD_EXTENSION = "extension";
|
||||
public static final String FIELD_USAGE_SUMMARY = "usageSummary";
|
||||
public static final String FIELD_DOMAIN = "domain";
|
||||
public static final String FIELD_DATA_PRODUCTS = "dataProducts";
|
||||
|
||||
//
|
||||
// Service entities
|
||||
@ -132,6 +134,7 @@ public final class Entity {
|
||||
// Domain related entities
|
||||
//
|
||||
public static final String DOMAIN = "domain";
|
||||
public static final String DATA_PRODUCT = "dataProduct";
|
||||
|
||||
//
|
||||
// Reserved names in OpenMetadata
|
||||
|
@ -81,6 +81,7 @@ import org.openmetadata.schema.entity.data.Query;
|
||||
import org.openmetadata.schema.entity.data.Report;
|
||||
import org.openmetadata.schema.entity.data.Table;
|
||||
import org.openmetadata.schema.entity.data.Topic;
|
||||
import org.openmetadata.schema.entity.domains.DataProduct;
|
||||
import org.openmetadata.schema.entity.domains.Domain;
|
||||
import org.openmetadata.schema.entity.events.EventSubscription;
|
||||
import org.openmetadata.schema.entity.policies.Policy;
|
||||
@ -198,6 +199,9 @@ public interface CollectionDAO {
|
||||
@CreateSqlObject
|
||||
DomainDAO domainDAO();
|
||||
|
||||
@CreateSqlObject
|
||||
DataProductDAO dataProductDAO();
|
||||
|
||||
@CreateSqlObject
|
||||
EventSubscriptionDAO eventSubscriptionDAO();
|
||||
|
||||
@ -1378,6 +1382,28 @@ public interface CollectionDAO {
|
||||
}
|
||||
}
|
||||
|
||||
interface DataProductDAO extends EntityDAO<DataProduct> {
|
||||
@Override
|
||||
default String getTableName() {
|
||||
return "data_product_entity";
|
||||
}
|
||||
|
||||
@Override
|
||||
default Class<DataProduct> getEntityClass() {
|
||||
return DataProduct.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
default String getNameHashColumn() {
|
||||
return "fqnHash";
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean supportsSoftDelete() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
interface EventSubscriptionDAO extends EntityDAO<EventSubscription> {
|
||||
@Override
|
||||
default String getTableName() {
|
||||
|
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2021 Collate
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openmetadata.service.jdbi3;
|
||||
|
||||
import static org.openmetadata.common.utils.CommonUtil.listOrEmpty;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.openmetadata.schema.entity.domains.DataProduct;
|
||||
import org.openmetadata.schema.type.EntityReference;
|
||||
import org.openmetadata.schema.type.Relationship;
|
||||
import org.openmetadata.service.Entity;
|
||||
import org.openmetadata.service.jdbi3.CollectionDAO.EntityRelationshipRecord;
|
||||
import org.openmetadata.service.resources.domains.DataProductResource;
|
||||
import org.openmetadata.service.util.EntityUtil;
|
||||
import org.openmetadata.service.util.EntityUtil.Fields;
|
||||
import org.openmetadata.service.util.FullyQualifiedName;
|
||||
|
||||
@Slf4j
|
||||
public class DataProductRepository extends EntityRepository<DataProduct> {
|
||||
private static final String UPDATE_FIELDS = "domain,owner,experts"; // Domain field can't be updated
|
||||
|
||||
public DataProductRepository(CollectionDAO dao) {
|
||||
super(
|
||||
DataProductResource.COLLECTION_PATH,
|
||||
Entity.DATA_PRODUCT,
|
||||
DataProduct.class,
|
||||
dao.dataProductDAO(),
|
||||
dao,
|
||||
UPDATE_FIELDS,
|
||||
UPDATE_FIELDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataProduct setFields(DataProduct entity, Fields fields) throws IOException {
|
||||
return entity.withExperts(fields.contains("experts") ? getExperts(entity) : null);
|
||||
}
|
||||
|
||||
// TODO to to inheritance for experts
|
||||
private List<EntityReference> getExperts(DataProduct entity) throws IOException {
|
||||
List<EntityRelationshipRecord> ids = findTo(entity.getId(), Entity.DATA_PRODUCT, Relationship.EXPERT, Entity.USER);
|
||||
return EntityUtil.populateEntityReferences(ids, Entity.USER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepare(DataProduct entity) throws IOException {
|
||||
// Parent, Experts, Owner are already validated
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeEntity(DataProduct entity, boolean update) throws IOException {
|
||||
EntityReference domain = entity.getDomain();
|
||||
List<EntityReference> experts = entity.getExperts();
|
||||
entity.withDomain(null).withExperts(null);
|
||||
store(entity, update);
|
||||
entity.withDomain(domain).withExperts(experts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeRelationships(DataProduct entity) {
|
||||
addRelationship(
|
||||
entity.getDomain().getId(), entity.getId(), Entity.DOMAIN, Entity.DATA_PRODUCT, Relationship.CONTAINS);
|
||||
for (EntityReference expert : listOrEmpty(entity.getExperts())) {
|
||||
addRelationship(entity.getId(), expert.getId(), Entity.DATA_PRODUCT, Entity.USER, Relationship.EXPERT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityUpdater getUpdater(DataProduct original, DataProduct updated, Operation operation) {
|
||||
return new DataProductUpdater(original, updated, operation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restorePatchAttributes(DataProduct original, DataProduct updated) {
|
||||
updated.withDomain(original.getDomain()); // Domain can't be changed
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFullyQualifiedName(DataProduct entity) {
|
||||
EntityReference domain = entity.getDomain();
|
||||
entity.setFullyQualifiedName(FullyQualifiedName.add(domain.getFullyQualifiedName(), entity.getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullyQualifiedNameHash(DataProduct entity) {
|
||||
return FullyQualifiedName.buildHash(entity.getFullyQualifiedName());
|
||||
}
|
||||
|
||||
public class DataProductUpdater extends EntityUpdater {
|
||||
public DataProductUpdater(DataProduct original, DataProduct updated, Operation operation) {
|
||||
super(original, updated, operation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void entitySpecificUpdate() throws IOException {
|
||||
updateExperts();
|
||||
}
|
||||
|
||||
private void updateExperts() throws JsonProcessingException {
|
||||
List<EntityReference> origExperts = listOrEmpty(original.getExperts());
|
||||
List<EntityReference> updatedExperts = listOrEmpty(updated.getExperts());
|
||||
updateToRelationships(
|
||||
"experts",
|
||||
Entity.DATA_PRODUCT,
|
||||
original.getId(),
|
||||
Relationship.EXPERT,
|
||||
Entity.USER,
|
||||
origExperts,
|
||||
updatedExperts,
|
||||
false);
|
||||
}
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ import org.openmetadata.service.util.FullyQualifiedName;
|
||||
|
||||
@Slf4j
|
||||
public class DomainRepository extends EntityRepository<Domain> {
|
||||
private static final String UPDATE_FIELDS = "owner,experts";
|
||||
private static final String UPDATE_FIELDS = "parent,children,owner,experts";
|
||||
|
||||
public DomainRepository(CollectionDAO dao) {
|
||||
super(
|
||||
@ -50,8 +50,7 @@ public class DomainRepository extends EntityRepository<Domain> {
|
||||
public Domain setFields(Domain entity, Fields fields) throws IOException {
|
||||
entity.withParent(fields.contains("parent") ? getParent(entity) : null);
|
||||
entity.withChildren(fields.contains("children") ? getChildren(entity) : null);
|
||||
entity.withExperts(fields.contains("experts") ? getExperts(entity) : null);
|
||||
return entity.withOwner(fields.contains("owner") ? getOwner(entity) : null);
|
||||
return entity.withExperts(fields.contains("experts") ? getExperts(entity) : null);
|
||||
}
|
||||
|
||||
private EntityReference getParent(Domain entity) throws IOException {
|
||||
|
@ -19,9 +19,13 @@ import static org.openmetadata.schema.type.Include.ALL;
|
||||
import static org.openmetadata.schema.type.Include.DELETED;
|
||||
import static org.openmetadata.schema.type.Include.NON_DELETED;
|
||||
import static org.openmetadata.service.Entity.ADMIN_USER_NAME;
|
||||
import static org.openmetadata.service.Entity.DATA_PRODUCT;
|
||||
import static org.openmetadata.service.Entity.DOMAIN;
|
||||
import static org.openmetadata.service.Entity.FIELD_DATA_PRODUCTS;
|
||||
import static org.openmetadata.service.Entity.FIELD_DELETED;
|
||||
import static org.openmetadata.service.Entity.FIELD_DESCRIPTION;
|
||||
import static org.openmetadata.service.Entity.FIELD_DISPLAY_NAME;
|
||||
import static org.openmetadata.service.Entity.FIELD_DOMAIN;
|
||||
import static org.openmetadata.service.Entity.FIELD_EXTENSION;
|
||||
import static org.openmetadata.service.Entity.FIELD_FOLLOWERS;
|
||||
import static org.openmetadata.service.Entity.FIELD_OWNER;
|
||||
@ -163,6 +167,8 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
||||
@Getter protected final boolean supportsOwner;
|
||||
protected final boolean supportsFollower;
|
||||
protected final boolean supportsVotes;
|
||||
protected final boolean supportsDomain;
|
||||
protected final boolean supportsDataProducts;
|
||||
|
||||
/** Fields that can be updated during PATCH operation */
|
||||
@Getter private final Fields patchFields;
|
||||
@ -192,6 +198,8 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
||||
this.supportsSoftDelete = allowedFields.contains(FIELD_DELETED);
|
||||
this.supportsFollower = allowedFields.contains(FIELD_FOLLOWERS);
|
||||
this.supportsVotes = allowedFields.contains(FIELD_VOTES);
|
||||
this.supportsDomain = allowedFields.contains(FIELD_DOMAIN);
|
||||
this.supportsDataProducts = allowedFields.contains(FIELD_DATA_PRODUCTS);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -547,11 +555,14 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
||||
prepare(entity);
|
||||
setFullyQualifiedName(entity);
|
||||
validateExtension(entity);
|
||||
// Domain is already validated
|
||||
}
|
||||
|
||||
public void storeRelationshipsInternal(T entity) throws IOException {
|
||||
storeOwner(entity, entity.getOwner());
|
||||
applyTags(entity);
|
||||
storeDomain(entity, entity.getDomain());
|
||||
storeDataProducts(entity, entity.getDataProducts());
|
||||
storeRelationships(entity);
|
||||
}
|
||||
|
||||
@ -559,6 +570,8 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
||||
entity.setOwner(fields.contains(FIELD_OWNER) ? getOwner(entity) : null);
|
||||
entity.setTags(fields.contains(FIELD_TAGS) ? getTags(entity.getFullyQualifiedName()) : null);
|
||||
entity.setExtension(fields.contains(FIELD_EXTENSION) ? getExtension(entity) : null);
|
||||
entity.setDomain(fields.contains(FIELD_DOMAIN) ? getDomain(entity) : null);
|
||||
entity.setDataProducts(fields.contains(FIELD_DATA_PRODUCTS) ? getDataProducts(entity) : null);
|
||||
setFields(entity, fields);
|
||||
setInheritedFields(entity);
|
||||
return entity;
|
||||
@ -901,6 +914,10 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
||||
entity.setOwner(null);
|
||||
List<TagLabel> tags = entity.getTags();
|
||||
entity.setTags(null);
|
||||
EntityReference domain = entity.getDomain();
|
||||
entity.setDomain(null);
|
||||
List<EntityReference> dataProducts = entity.getDataProducts();
|
||||
entity.setDataProducts(null);
|
||||
|
||||
if (update) {
|
||||
dao.update(entity.getId(), getFullyQualifiedNameHash(entity), JsonUtils.pojoToJson(entity));
|
||||
@ -913,6 +930,8 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
||||
// Restore the relationships
|
||||
entity.setOwner(owner);
|
||||
entity.setTags(tags);
|
||||
entity.setDomain(domain);
|
||||
entity.setDataProducts(dataProducts);
|
||||
}
|
||||
|
||||
protected void storeTimeSeries(
|
||||
@ -990,7 +1009,7 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
||||
daoCollection.entityExtensionTimeSeriesDao().deleteBeforeTimestamp(fqnHash, extension, timestamp);
|
||||
}
|
||||
|
||||
public void validateExtension(T entity) {
|
||||
private void validateExtension(T entity) {
|
||||
if (entity.getExtension() == null) {
|
||||
return;
|
||||
}
|
||||
@ -1357,6 +1376,18 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
||||
return !supportsOwner ? null : getFromEntityRef(entity.getId(), Relationship.OWNS, null, false);
|
||||
}
|
||||
|
||||
public EntityReference getDomain(T entity) throws IOException {
|
||||
return getFromEntityRef(entity.getId(), Relationship.HAS, DOMAIN, false);
|
||||
}
|
||||
|
||||
private List<EntityReference> getDataProducts(T entity) throws IOException {
|
||||
if (!supportsDataProducts || entity == null) {
|
||||
return null;
|
||||
}
|
||||
List<EntityRelationshipRecord> ids = findFrom(entity.getId(), entityType, Relationship.HAS, DATA_PRODUCT);
|
||||
return EntityUtil.populateEntityReferences(ids, entityType);
|
||||
}
|
||||
|
||||
public EntityReference getOwner(EntityReference ref) throws IOException {
|
||||
return !supportsOwner ? null : Entity.getEntityReferenceById(ref.getType(), ref.getId(), ALL);
|
||||
}
|
||||
@ -1372,15 +1403,39 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
||||
protected void storeOwner(T entity, EntityReference owner) {
|
||||
if (supportsOwner && owner != null) {
|
||||
// Add relationship owner --- owns ---> ownedEntity
|
||||
LOG.info("Adding owner {}:{} for entity {}:{}", owner.getType(), owner.getId(), entityType, entity.getId());
|
||||
LOG.info(
|
||||
"Adding owner {}:{} for entity {}:{}",
|
||||
owner.getType(),
|
||||
owner.getFullyQualifiedName(),
|
||||
entityType,
|
||||
entity.getId());
|
||||
addRelationship(owner.getId(), entity.getId(), owner.getType(), entityType, Relationship.OWNS);
|
||||
}
|
||||
}
|
||||
|
||||
protected void storeDomain(T entity, EntityReference domain) {
|
||||
if (supportsDomain && domain != null) {
|
||||
// Add relationship domain --- has ---> entity
|
||||
LOG.info("Adding domain {} for entity {}:{}", domain.getFullyQualifiedName(), entityType, entity.getId());
|
||||
addRelationship(domain.getId(), entity.getId(), Entity.DOMAIN, entityType, Relationship.HAS);
|
||||
}
|
||||
}
|
||||
|
||||
protected void storeDataProducts(T entity, List<EntityReference> dataProducts) {
|
||||
if (supportsDataProducts && !nullOrEmpty(dataProducts)) {
|
||||
for (EntityReference dataProduct : dataProducts) {
|
||||
// Add relationship dataProduct --- has ---> entity
|
||||
LOG.info(
|
||||
"Adding dataProduct {} for entity {}:{}", dataProduct.getFullyQualifiedName(), entityType, entity.getId());
|
||||
addRelationship(dataProduct.getId(), entity.getId(), Entity.DATA_PRODUCT, entityType, Relationship.HAS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove owner relationship for a given entity */
|
||||
private void removeOwner(T entity, EntityReference owner) {
|
||||
if (EntityUtil.getId(owner) != null) {
|
||||
LOG.info("Removing owner {}:{} for entity {}", owner.getType(), owner.getId(), entity.getId());
|
||||
LOG.info("Removing owner {}:{} for entity {}", owner.getType(), owner.getFullyQualifiedName(), entity.getId());
|
||||
deleteRelationship(owner.getId(), owner.getType(), entity.getId(), entityType, Relationship.OWNS);
|
||||
}
|
||||
}
|
||||
@ -1457,6 +1512,13 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
||||
return Entity.getEntityReferenceById(owner.getType(), owner.getId(), ALL);
|
||||
}
|
||||
|
||||
public EntityReference validateDomain(String domainFqn) throws IOException {
|
||||
if (!supportsDomain || domainFqn == null) {
|
||||
return null;
|
||||
}
|
||||
return Entity.getEntityReferenceByName(Entity.DOMAIN, domainFqn, NON_DELETED);
|
||||
}
|
||||
|
||||
/** Override this method to support downloading CSV functionality */
|
||||
public String exportToCsv(String name, String user) throws IOException {
|
||||
throw new IllegalArgumentException(csvNotSupported(entityType));
|
||||
@ -1531,6 +1593,8 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
||||
updateOwner();
|
||||
updateExtension();
|
||||
updateTags(updated.getFullyQualifiedName(), FIELD_TAGS, original.getTags(), updated.getTags());
|
||||
updateDomain();
|
||||
updateDataProducts();
|
||||
entitySpecificUpdate();
|
||||
}
|
||||
|
||||
@ -1664,6 +1728,47 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
||||
storeExtension(updated);
|
||||
}
|
||||
|
||||
private void updateDomain() throws JsonProcessingException {
|
||||
if (original.getDomain() == updated.getDomain()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityReference origDomain = original.getDomain();
|
||||
EntityReference updatedDomain = updated.getDomain();
|
||||
if ((operation.isPatch() || updatedDomain != null)
|
||||
&& recordChange(FIELD_DOMAIN, origDomain, updatedDomain, true, entityReferenceMatch)) {
|
||||
if (origDomain != null) {
|
||||
LOG.info(
|
||||
"Removing domain {} for entity {}", origDomain.getFullyQualifiedName(), original.getFullyQualifiedName());
|
||||
deleteRelationship(origDomain.getId(), Entity.DOMAIN, original.getId(), entityType, Relationship.HAS);
|
||||
}
|
||||
if (updatedDomain != null) {
|
||||
// Add relationship owner --- owns ---> ownedEntity
|
||||
LOG.info(
|
||||
"Adding domain {} for entity {}",
|
||||
updatedDomain.getFullyQualifiedName(),
|
||||
original.getFullyQualifiedName());
|
||||
addRelationship(updatedDomain.getId(), original.getId(), Entity.DOMAIN, entityType, Relationship.HAS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDataProducts() throws JsonProcessingException {
|
||||
if (!supportsDataProducts) {
|
||||
return;
|
||||
}
|
||||
List<EntityReference> origDataProducts = listOrEmpty(original.getDataProducts());
|
||||
List<EntityReference> updatedDataProducts = listOrEmpty(updated.getDataProducts());
|
||||
updateFromRelationships(
|
||||
"dataProducts",
|
||||
DATA_PRODUCT,
|
||||
origDataProducts,
|
||||
updatedDataProducts,
|
||||
Relationship.HAS,
|
||||
entityType,
|
||||
original.getId());
|
||||
}
|
||||
|
||||
public final boolean updateVersion(Double oldVersion) {
|
||||
Double newVersion = oldVersion;
|
||||
if (majorVersionChange) {
|
||||
|
@ -217,7 +217,6 @@ public abstract class EntityResource<T extends EntityInterface, K extends Entity
|
||||
OperationContext operationContext = new OperationContext(entityType, CREATE);
|
||||
authorizer.authorize(securityContext, operationContext, getResourceContext());
|
||||
entity = addHref(uriInfo, repository.create(uriInfo, entity));
|
||||
LOG.info("Created {}:{}", Entity.getEntityTypeFromObject(entity), entity.getId());
|
||||
return Response.created(entity.getHref()).entity(entity).build();
|
||||
}
|
||||
|
||||
@ -288,11 +287,14 @@ public abstract class EntityResource<T extends EntityInterface, K extends Entity
|
||||
|
||||
public T copy(T entity, CreateEntity request, String updatedBy) throws IOException {
|
||||
EntityReference owner = repository.validateOwner(request.getOwner());
|
||||
EntityReference domain = repository.validateDomain(request.getDomain());
|
||||
entity.setId(UUID.randomUUID());
|
||||
entity.setName(request.getName());
|
||||
entity.setDisplayName(request.getDisplayName());
|
||||
entity.setDescription(request.getDescription());
|
||||
entity.setOwner(owner);
|
||||
entity.setDomain(domain);
|
||||
entity.setDataProducts(getEntityReferences(Entity.DATA_PRODUCT, request.getDataProducts()));
|
||||
entity.setExtension(request.getExtension());
|
||||
entity.setUpdatedBy(updatedBy);
|
||||
entity.setUpdatedAt(System.currentTimeMillis());
|
||||
|
@ -73,7 +73,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
@Collection(name = "charts")
|
||||
public class ChartResource extends EntityResource<Chart, ChartRepository> {
|
||||
public static final String COLLECTION_PATH = "v1/charts/";
|
||||
static final String FIELDS = "owner,followers,tags";
|
||||
static final String FIELDS = "owner,followers,tags,domain,dataProducts";
|
||||
|
||||
@Override
|
||||
public Chart addHref(UriInfo uriInfo, Chart chart) {
|
||||
|
@ -73,7 +73,8 @@ import org.openmetadata.service.util.ResultList;
|
||||
@Collection(name = "dashboards")
|
||||
public class DashboardResource extends EntityResource<Dashboard, DashboardRepository> {
|
||||
public static final String COLLECTION_PATH = "v1/dashboards/";
|
||||
protected static final String FIELDS = "owner,charts,followers,tags,usageSummary,extension,dataModels";
|
||||
protected static final String FIELDS =
|
||||
"owner,charts,followers,tags,usageSummary,extension,dataModels," + "domain,dataProducts";
|
||||
|
||||
@Override
|
||||
public Dashboard addHref(UriInfo uriInfo, Dashboard dashboard) {
|
||||
|
@ -71,7 +71,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
@Collection(name = "databases")
|
||||
public class DatabaseResource extends EntityResource<Database, DatabaseRepository> {
|
||||
public static final String COLLECTION_PATH = "v1/databases/";
|
||||
static final String FIELDS = "owner,databaseSchemas,usageSummary,location,tags,extension";
|
||||
static final String FIELDS = "owner,databaseSchemas,usageSummary,location,tags,extension,domain";
|
||||
|
||||
@Override
|
||||
public Database addHref(UriInfo uriInfo, Database db) {
|
||||
|
@ -71,7 +71,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
@Collection(name = "databaseSchemas")
|
||||
public class DatabaseSchemaResource extends EntityResource<DatabaseSchema, DatabaseSchemaRepository> {
|
||||
public static final String COLLECTION_PATH = "v1/databaseSchemas/";
|
||||
static final String FIELDS = "owner,tables,usageSummary,tags,extension";
|
||||
static final String FIELDS = "owner,tables,usageSummary,tags,extension,domain";
|
||||
|
||||
@Override
|
||||
public DatabaseSchema addHref(UriInfo uriInfo, DatabaseSchema schema) {
|
||||
|
@ -84,6 +84,9 @@ import org.openmetadata.service.util.ResultList;
|
||||
@Collection(name = "tables")
|
||||
public class TableResource extends EntityResource<Table, TableRepository> {
|
||||
public static final String COLLECTION_PATH = "v1/tables/";
|
||||
static final String FIELDS =
|
||||
"tableConstraints,tablePartition,usageSummary,owner,customMetrics,"
|
||||
+ "tags,followers,joins,viewDefinition,dataModel,extension,testSuite,domain,dataProducts";
|
||||
|
||||
@Override
|
||||
public Table addHref(UriInfo uriInfo, Table table) {
|
||||
@ -136,10 +139,6 @@ public class TableResource extends EntityResource<Table, TableRepository> {
|
||||
/* Required for serde */
|
||||
}
|
||||
|
||||
static final String FIELDS =
|
||||
"tableConstraints,tablePartition,usageSummary,owner,customMetrics,"
|
||||
+ "tags,followers,joins,viewDefinition,dataModel,extension,testSuite";
|
||||
|
||||
@GET
|
||||
@Operation(
|
||||
operationId = "listTables",
|
||||
|
@ -70,7 +70,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
@Collection(name = "datamodels")
|
||||
public class DashboardDataModelResource extends EntityResource<DashboardDataModel, DashboardDataModelRepository> {
|
||||
public static final String COLLECTION_PATH = "/v1/dashboard/datamodels";
|
||||
protected static final String FIELDS = "owner,tags,followers";
|
||||
protected static final String FIELDS = "owner,tags,followers,domain";
|
||||
|
||||
@Override
|
||||
public DashboardDataModel addHref(UriInfo uriInfo, DashboardDataModel dashboardDataModel) {
|
||||
|
@ -0,0 +1,341 @@
|
||||
/*
|
||||
* Copyright 2021 Collate
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openmetadata.service.resources.domains;
|
||||
|
||||
import io.swagger.v3.oas.annotations.ExternalDocumentation;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
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.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.json.JsonPatch;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PATCH;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.SecurityContext;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.openmetadata.schema.api.domains.CreateDataProduct;
|
||||
import org.openmetadata.schema.entity.domains.DataProduct;
|
||||
import org.openmetadata.schema.type.EntityHistory;
|
||||
import org.openmetadata.schema.utils.EntityInterfaceUtil;
|
||||
import org.openmetadata.service.Entity;
|
||||
import org.openmetadata.service.jdbi3.CollectionDAO;
|
||||
import org.openmetadata.service.jdbi3.DataProductRepository;
|
||||
import org.openmetadata.service.jdbi3.ListFilter;
|
||||
import org.openmetadata.service.resources.Collection;
|
||||
import org.openmetadata.service.resources.EntityResource;
|
||||
import org.openmetadata.service.security.Authorizer;
|
||||
import org.openmetadata.service.util.EntityUtil;
|
||||
import org.openmetadata.service.util.RestUtil;
|
||||
import org.openmetadata.service.util.ResultList;
|
||||
|
||||
@Slf4j
|
||||
@Path("/v1/dataProducts")
|
||||
@Tag(
|
||||
name = "Domains",
|
||||
description =
|
||||
"A `Data Product` or `Data as a Product` is a logical unit that contains all components to process and store "
|
||||
+ "domain data for analytical or data-intensive use cases made available to data consumers.")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Collection(name = "dataProducts", order = 4) // initialize after user resource
|
||||
public class DataProductResource extends EntityResource<DataProduct, DataProductRepository> {
|
||||
public static final String COLLECTION_PATH = "/v1/dataProducts/";
|
||||
static final String FIELDS = "domain,owner,experts";
|
||||
|
||||
public DataProductResource(CollectionDAO dao, Authorizer authorizer) {
|
||||
super(DataProduct.class, new DataProductRepository(dao), authorizer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataProduct addHref(UriInfo uriInfo, DataProduct dataProduct) {
|
||||
dataProduct.withHref(RestUtil.getHref(uriInfo, COLLECTION_PATH, dataProduct.getId()));
|
||||
Entity.withHref(uriInfo, dataProduct.getExperts());
|
||||
Entity.withHref(uriInfo, dataProduct.getOwner());
|
||||
Entity.withHref(uriInfo, dataProduct.getDomain());
|
||||
return dataProduct;
|
||||
}
|
||||
|
||||
public static class DataProductList extends ResultList<DataProduct> {
|
||||
@SuppressWarnings("unused")
|
||||
public DataProductList() {
|
||||
/* Required for serde */
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Operation(
|
||||
operationId = "listDataProducts",
|
||||
summary = "List dataProducts",
|
||||
description = "Get a list of DataProducts.",
|
||||
responses = {
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "List of DataProducts",
|
||||
content =
|
||||
@Content(mediaType = "application/json", schema = @Schema(implementation = DataProductList.class)))
|
||||
})
|
||||
public ResultList<DataProduct> list(
|
||||
@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@Parameter(
|
||||
description = "Fields requested in the returned resource",
|
||||
schema = @Schema(type = "string", example = FIELDS))
|
||||
@QueryParam("fields")
|
||||
String fieldsParam,
|
||||
@DefaultValue("10") @Min(0) @Max(1000000) @QueryParam("limit") int limitParam,
|
||||
@Parameter(description = "Returns list of DataProduct before this cursor", schema = @Schema(type = "string"))
|
||||
@QueryParam("before")
|
||||
String before,
|
||||
@Parameter(description = "Returns list of DataProduct after this cursor", schema = @Schema(type = "string"))
|
||||
@QueryParam("after")
|
||||
String after)
|
||||
throws IOException {
|
||||
return listInternal(uriInfo, securityContext, fieldsParam, new ListFilter(null), limitParam, before, after);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
@Operation(
|
||||
operationId = "getDataProductByID",
|
||||
summary = "Get a dataProduct by Id",
|
||||
description = "Get a dataProduct by `Id`.",
|
||||
responses = {
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "The dataProduct",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(implementation = DataProduct.class))),
|
||||
@ApiResponse(responseCode = "404", description = "DataProduct for instance {id} is not found")
|
||||
})
|
||||
public DataProduct get(
|
||||
@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@Parameter(
|
||||
description = "Fields requested in the returned resource",
|
||||
schema = @Schema(type = "string", example = FIELDS))
|
||||
@QueryParam("fields")
|
||||
String fieldsParam,
|
||||
@Parameter(description = "Id of the dataProduct", schema = @Schema(type = "UUID")) @PathParam("id") UUID id)
|
||||
throws IOException {
|
||||
return getInternal(uriInfo, securityContext, id, fieldsParam, null);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/name/{name}")
|
||||
@Operation(
|
||||
operationId = "getDataProductByFQN",
|
||||
summary = "Get a dataProduct by name",
|
||||
description = "Get a dataProduct by `name`.",
|
||||
responses = {
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "dataProduct",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(implementation = DataProduct.class))),
|
||||
@ApiResponse(responseCode = "404", description = "DataProduct for instance {name} is not found")
|
||||
})
|
||||
public DataProduct getByName(
|
||||
@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@Parameter(description = "Name of the dataProduct", schema = @Schema(type = "string")) @PathParam("name")
|
||||
String name,
|
||||
@Parameter(
|
||||
description = "Fields requested in the returned resource",
|
||||
schema = @Schema(type = "string", example = FIELDS))
|
||||
@QueryParam("fields")
|
||||
String fieldsParam)
|
||||
throws IOException {
|
||||
return getByNameInternal(uriInfo, securityContext, name, fieldsParam, null);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{id}/versions")
|
||||
@Operation(
|
||||
operationId = "listAllDataProductVersion",
|
||||
summary = "List dataProduct versions",
|
||||
description = "Get a list of all the versions of a dataProduct identified by `Id`",
|
||||
responses = {
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "List of dataProduct versions",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(implementation = EntityHistory.class)))
|
||||
})
|
||||
public EntityHistory listVersions(
|
||||
@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@Parameter(description = "Id of the dataProduct", schema = @Schema(type = "UUID")) @PathParam("id") UUID id)
|
||||
throws IOException {
|
||||
return super.listVersionsInternal(securityContext, id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{id}/versions/{version}")
|
||||
@Operation(
|
||||
operationId = "listSpecificDataProductVersion",
|
||||
summary = "Get a version of the dataProduct",
|
||||
description = "Get a version of the dataProduct by given `Id`",
|
||||
responses = {
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "dataProduct",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(implementation = DataProduct.class))),
|
||||
@ApiResponse(
|
||||
responseCode = "404",
|
||||
description = "DataProduct for instance {id} and version {version} is " + "not found")
|
||||
})
|
||||
public DataProduct getVersion(
|
||||
@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@Parameter(description = "Id of the dataProduct", schema = @Schema(type = "UUID")) @PathParam("id") UUID id,
|
||||
@Parameter(
|
||||
description = "DataProduct version number in the form `major`.`minor`",
|
||||
schema = @Schema(type = "string", example = "0.1 or 1.1"))
|
||||
@PathParam("version")
|
||||
String version)
|
||||
throws IOException {
|
||||
return super.getVersionInternal(securityContext, id, version);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Operation(
|
||||
operationId = "createDataProduct",
|
||||
summary = "Create a dataProduct",
|
||||
description = "Create a new dataProduct.",
|
||||
responses = {
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "The dataProduct ",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(implementation = DataProduct.class))),
|
||||
@ApiResponse(responseCode = "400", description = "Bad request")
|
||||
})
|
||||
public Response create(
|
||||
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateDataProduct create)
|
||||
throws IOException {
|
||||
DataProduct dataProduct = getDataProduct(create, securityContext.getUserPrincipal().getName());
|
||||
return create(uriInfo, securityContext, dataProduct);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Operation(
|
||||
operationId = "createOrUpdateDataProduct",
|
||||
summary = "Create or update a dataProduct",
|
||||
description =
|
||||
"Create a dataProduct. if it does not exist. If a dataProduct already exists, update the " + "dataProduct.",
|
||||
responses = {
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "The dataProduct",
|
||||
content = @Content(mediaType = "application/json", schema = @Schema(implementation = DataProduct.class))),
|
||||
@ApiResponse(responseCode = "400", description = "Bad request")
|
||||
})
|
||||
public Response createOrUpdate(
|
||||
@Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateDataProduct create)
|
||||
throws IOException {
|
||||
DataProduct dataProduct = getDataProduct(create, securityContext.getUserPrincipal().getName());
|
||||
return createOrUpdate(uriInfo, securityContext, dataProduct);
|
||||
}
|
||||
|
||||
@PATCH
|
||||
@Path("/{id}")
|
||||
@Operation(
|
||||
operationId = "patchDataProduct",
|
||||
summary = "Update a dataProduct",
|
||||
description = "Update an existing dataProduct 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,
|
||||
@Parameter(description = "Id of the dataProduct", schema = @Schema(type = "UUID")) @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
|
||||
@Path("/{id}")
|
||||
@Operation(
|
||||
operationId = "deleteDataProduct",
|
||||
summary = "Delete a dataProduct by Id",
|
||||
description = "Delete a dataProduct by `Id`.",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK"),
|
||||
@ApiResponse(responseCode = "404", description = "DataProduct for instance {id} is not found")
|
||||
})
|
||||
public Response delete(
|
||||
@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@Parameter(description = "Id of the dataProduct", schema = @Schema(type = "UUID")) @PathParam("id") UUID id)
|
||||
throws IOException {
|
||||
return delete(uriInfo, securityContext, id, true, true);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("/name/{name}")
|
||||
@Operation(
|
||||
operationId = "deleteDataProductByFQN",
|
||||
summary = "Delete a dataProduct by name",
|
||||
description = "Delete a dataProduct by `name`.",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK"),
|
||||
@ApiResponse(responseCode = "404", description = "DataProduct for instance {name} is not found")
|
||||
})
|
||||
public Response delete(
|
||||
@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@Parameter(description = "Name of the dataProduct", schema = @Schema(type = "string")) @PathParam("name")
|
||||
String name)
|
||||
throws IOException {
|
||||
return deleteByName(uriInfo, securityContext, name, true, true);
|
||||
}
|
||||
|
||||
private DataProduct getDataProduct(CreateDataProduct create, String user) throws IOException {
|
||||
List<String> experts =
|
||||
create.getExperts() == null
|
||||
? create.getExperts()
|
||||
: create.getExperts().stream().map(EntityInterfaceUtil::quoteName).collect(Collectors.toList());
|
||||
return copy(new DataProduct(), create, user)
|
||||
.withFullyQualifiedName(create.getName())
|
||||
.withExperts(EntityUtil.populateEntityReferences(getEntityReferences(Entity.USER, experts)));
|
||||
}
|
||||
}
|
@ -50,6 +50,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.openmetadata.schema.api.domains.CreateDomain;
|
||||
import org.openmetadata.schema.entity.domains.Domain;
|
||||
import org.openmetadata.schema.type.EntityHistory;
|
||||
import org.openmetadata.schema.type.Include;
|
||||
import org.openmetadata.schema.utils.EntityInterfaceUtil;
|
||||
import org.openmetadata.service.Entity;
|
||||
import org.openmetadata.service.jdbi3.CollectionDAO;
|
||||
@ -332,7 +333,8 @@ public class DomainResource extends EntityResource<Domain, DomainRepository> {
|
||||
return copy(new Domain(), create, user)
|
||||
.withDomainType(create.getDomainType())
|
||||
.withFullyQualifiedName(create.getName())
|
||||
.withParent(getEntityReference(Entity.DOMAIN, create.getParent()))
|
||||
.withParent(
|
||||
Entity.getEntityReference(getEntityReference(Entity.DOMAIN, create.getParent()), Include.NON_DELETED))
|
||||
.withExperts(EntityUtil.populateEntityReferences(getEntityReferences(Entity.USER, experts)));
|
||||
}
|
||||
}
|
||||
|
@ -339,7 +339,6 @@ public class TestCaseResource extends EntityResource<TestCase, TestCaseRepositor
|
||||
authorizer.authorize(securityContext, operationContext, resourceContext);
|
||||
repository.isTestSuiteExecutable(create.getTestSuite());
|
||||
test = addHref(uriInfo, repository.create(uriInfo, test));
|
||||
LOG.info("Created {}:{}", Entity.getEntityTypeFromObject(test), test.getId());
|
||||
return Response.created(test.getHref()).entity(test).build();
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
@Collection(name = "glossaries", order = 6) // Initialize before GlossaryTerm and after Classification and Tags
|
||||
public class GlossaryResource extends EntityResource<Glossary, GlossaryRepository> {
|
||||
public static final String COLLECTION_PATH = "v1/glossaries/";
|
||||
static final String FIELDS = "owner,tags,reviewers,usageCount,termCount";
|
||||
static final String FIELDS = "owner,tags,reviewers,usageCount,termCount,domain";
|
||||
|
||||
@Override
|
||||
public Glossary addHref(UriInfo uriInfo, Glossary glossary) {
|
||||
|
@ -76,7 +76,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
@Collection(name = "glossaryTerms", order = 7) // Initialized after Glossary, Classification, and Tags
|
||||
public class GlossaryTermResource extends EntityResource<GlossaryTerm, GlossaryTermRepository> {
|
||||
public static final String COLLECTION_PATH = "v1/glossaryTerms/";
|
||||
static final String FIELDS = "children,relatedTerms,reviewers,owner,tags,usageCount";
|
||||
static final String FIELDS = "children,relatedTerms,reviewers,owner,tags,usageCount,domain";
|
||||
|
||||
@Override
|
||||
public GlossaryTerm addHref(UriInfo uriInfo, GlossaryTerm term) {
|
||||
|
@ -63,7 +63,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
@Collection(name = "metrics")
|
||||
public class MetricsResource extends EntityResource<Metrics, MetricsRepository> {
|
||||
public static final String COLLECTION_PATH = "/v1/metrics/";
|
||||
static final String FIELDS = "owner,usageSummary";
|
||||
static final String FIELDS = "owner,usageSummary,domain";
|
||||
|
||||
public MetricsResource(CollectionDAO dao, Authorizer authorizer) {
|
||||
super(Metrics.class, new MetricsRepository(dao), authorizer);
|
||||
|
@ -73,7 +73,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
@Collection(name = "mlmodels")
|
||||
public class MlModelResource extends EntityResource<MlModel, MlModelRepository> {
|
||||
public static final String COLLECTION_PATH = "v1/mlmodels/";
|
||||
static final String FIELDS = "owner,dashboard,followers,tags,usageSummary,extension";
|
||||
static final String FIELDS = "owner,dashboard,followers,tags,usageSummary,extension,domain";
|
||||
|
||||
@Override
|
||||
public MlModel addHref(UriInfo uriInfo, MlModel mlmodel) {
|
||||
|
@ -78,7 +78,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
@Collection(name = "pipelines")
|
||||
public class PipelineResource extends EntityResource<Pipeline, PipelineRepository> {
|
||||
public static final String COLLECTION_PATH = "v1/pipelines/";
|
||||
static final String FIELDS = "owner,tasks,pipelineStatus,followers,tags,extension,scheduleInterval";
|
||||
static final String FIELDS = "owner,tasks,pipelineStatus,followers,tags,extension,scheduleInterval,domain";
|
||||
|
||||
@Override
|
||||
public Pipeline addHref(UriInfo uriInfo, Pipeline pipeline) {
|
||||
|
@ -13,8 +13,6 @@
|
||||
|
||||
package org.openmetadata.service.resources.services.dashboard;
|
||||
|
||||
import static org.openmetadata.service.Entity.FIELD_OWNER;
|
||||
|
||||
import io.swagger.v3.oas.annotations.ExternalDocumentation;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@ -79,7 +77,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
public class DashboardServiceResource
|
||||
extends ServiceEntityResource<DashboardService, DashboardServiceRepository, DashboardConnection> {
|
||||
public static final String COLLECTION_PATH = "v1/services/dashboardServices";
|
||||
static final String FIELDS = FIELD_OWNER;
|
||||
static final String FIELDS = "owner,domain";
|
||||
|
||||
@Override
|
||||
public DashboardService addHref(UriInfo uriInfo, DashboardService service) {
|
||||
|
@ -83,7 +83,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
public class DatabaseServiceResource
|
||||
extends ServiceEntityResource<DatabaseService, DatabaseServiceRepository, DatabaseConnection> {
|
||||
public static final String COLLECTION_PATH = "v1/services/databaseServices/";
|
||||
static final String FIELDS = "pipelines,owner,tags";
|
||||
static final String FIELDS = "pipelines,owner,tags,domain";
|
||||
|
||||
@Override
|
||||
public DatabaseService addHref(UriInfo uriInfo, DatabaseService service) {
|
||||
|
@ -13,8 +13,6 @@
|
||||
|
||||
package org.openmetadata.service.resources.services.messaging;
|
||||
|
||||
import static org.openmetadata.service.Entity.FIELD_OWNER;
|
||||
|
||||
import io.swagger.v3.oas.annotations.ExternalDocumentation;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@ -79,7 +77,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
public class MessagingServiceResource
|
||||
extends ServiceEntityResource<MessagingService, MessagingServiceRepository, MessagingConnection> {
|
||||
public static final String COLLECTION_PATH = "v1/services/messagingServices/";
|
||||
public static final String FIELDS = FIELD_OWNER;
|
||||
public static final String FIELDS = "owner,domain";
|
||||
|
||||
@Override
|
||||
public MessagingService addHref(UriInfo uriInfo, MessagingService service) {
|
||||
|
@ -79,7 +79,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
public class MlModelServiceResource
|
||||
extends ServiceEntityResource<MlModelService, MlModelServiceRepository, MlModelConnection> {
|
||||
public static final String COLLECTION_PATH = "v1/services/mlmodelServices/";
|
||||
public static final String FIELDS = "pipelines,owner,tags";
|
||||
public static final String FIELDS = "pipelines,owner,tags,domain";
|
||||
|
||||
@Override
|
||||
public MlModelService addHref(UriInfo uriInfo, MlModelService service) {
|
||||
|
@ -77,7 +77,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
public class PipelineServiceResource
|
||||
extends ServiceEntityResource<PipelineService, PipelineServiceRepository, PipelineConnection> {
|
||||
public static final String COLLECTION_PATH = "v1/services/pipelineServices/";
|
||||
static final String FIELDS = "pipelines,owner";
|
||||
static final String FIELDS = "pipelines,owner,domain";
|
||||
|
||||
@Override
|
||||
public PipelineService addHref(UriInfo uriInfo, PipelineService service) {
|
||||
|
@ -69,7 +69,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
public class StorageServiceResource
|
||||
extends ServiceEntityResource<StorageService, StorageServiceRepository, StorageConnection> {
|
||||
public static final String COLLECTION_PATH = "v1/services/storageServices/";
|
||||
static final String FIELDS = "pipelines,owner,tags";
|
||||
static final String FIELDS = "pipelines,owner,tags,domain";
|
||||
|
||||
@Override
|
||||
public StorageService addHref(UriInfo uriInfo, StorageService service) {
|
||||
|
@ -61,7 +61,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
@Collection(name = "containers")
|
||||
public class ContainerResource extends EntityResource<Container, ContainerRepository> {
|
||||
public static final String COLLECTION_PATH = "v1/containers/";
|
||||
static final String FIELDS = "parent,children,dataModel,owner,tags,followers,extension";
|
||||
static final String FIELDS = "parent,children,dataModel,owner,tags,followers,extension,domain";
|
||||
|
||||
@Override
|
||||
public Container addHref(UriInfo uriInfo, Container container) {
|
||||
|
@ -85,6 +85,8 @@ import org.openmetadata.service.util.ResultList;
|
||||
@Collection(name = "teams", order = 2) // Load after roles, and policy resources
|
||||
public class TeamResource extends EntityResource<Team, TeamRepository> {
|
||||
public static final String COLLECTION_PATH = "/v1/teams/";
|
||||
static final String FIELDS =
|
||||
"owner,profile,users,owns,defaultRoles,parents,children,policies,userCount,childrenCount,domain";
|
||||
|
||||
@Override
|
||||
public Team addHref(UriInfo uriInfo, Team team) {
|
||||
@ -122,9 +124,6 @@ public class TeamResource extends EntityResource<Team, TeamRepository> {
|
||||
/* Required for serde */
|
||||
}
|
||||
|
||||
static final String FIELDS =
|
||||
"owner,profile,users,owns,defaultRoles,parents,children,policies,userCount,childrenCount";
|
||||
|
||||
@GET
|
||||
@Path("/hierarchy")
|
||||
@Valid
|
||||
|
@ -159,7 +159,7 @@ public class UserResource extends EntityResource<User, UserRepository> {
|
||||
private boolean isEmailServiceEnabled;
|
||||
private AuthenticationConfiguration authenticationConfiguration;
|
||||
private final AuthenticatorHandler authHandler;
|
||||
static final String FIELDS = "profile,roles,teams,follows,owns";
|
||||
static final String FIELDS = "profile,roles,teams,follows,owns,domain";
|
||||
|
||||
@Override
|
||||
public User addHref(UriInfo uriInfo, User user) {
|
||||
|
@ -77,7 +77,7 @@ import org.openmetadata.service.util.ResultList;
|
||||
@Collection(name = "topics")
|
||||
public class TopicResource extends EntityResource<Topic, TopicRepository> {
|
||||
public static final String COLLECTION_PATH = "v1/topics/";
|
||||
static final String FIELDS = "owner,followers,tags,extension";
|
||||
static final String FIELDS = "owner,followers,tags,extension,domain,dataProducts";
|
||||
|
||||
@Override
|
||||
public Topic addHref(UriInfo uriInfo, Topic topic) {
|
||||
|
@ -141,6 +141,8 @@ import org.openmetadata.schema.entity.data.DatabaseSchema;
|
||||
import org.openmetadata.schema.entity.data.Glossary;
|
||||
import org.openmetadata.schema.entity.data.GlossaryTerm;
|
||||
import org.openmetadata.schema.entity.data.Table;
|
||||
import org.openmetadata.schema.entity.domains.DataProduct;
|
||||
import org.openmetadata.schema.entity.domains.Domain;
|
||||
import org.openmetadata.schema.entity.policies.Policy;
|
||||
import org.openmetadata.schema.entity.policies.accessControl.Rule;
|
||||
import org.openmetadata.schema.entity.services.connections.TestConnectionResult;
|
||||
@ -172,6 +174,8 @@ import org.openmetadata.service.elasticsearch.ElasticSearchIndexDefinition;
|
||||
import org.openmetadata.service.exception.CatalogExceptionMessage;
|
||||
import org.openmetadata.service.resources.bots.BotResourceTest;
|
||||
import org.openmetadata.service.resources.databases.TableResourceTest;
|
||||
import org.openmetadata.service.resources.domains.DataProductResourceTest;
|
||||
import org.openmetadata.service.resources.domains.DomainResourceTest;
|
||||
import org.openmetadata.service.resources.dqtests.TestCaseResourceTest;
|
||||
import org.openmetadata.service.resources.dqtests.TestDefinitionResourceTest;
|
||||
import org.openmetadata.service.resources.dqtests.TestSuiteResourceTest;
|
||||
@ -328,6 +332,11 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
||||
public static final String C4 = "\"c.4\"";
|
||||
public static List<Column> COLUMNS;
|
||||
|
||||
public static Domain DOMAIN;
|
||||
public static Domain SUB_DOMAIN;
|
||||
public static DataProduct DOMAIN_DATA_PRODUCT;
|
||||
public static DataProduct SUB_DOMAIN_DATA_PRODUCT;
|
||||
|
||||
public static final TestConnectionResult TEST_CONNECTION_RESULT =
|
||||
new TestConnectionResult()
|
||||
.withStatus(TestConnectionResultStatus.SUCCESSFUL)
|
||||
@ -405,6 +414,8 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
||||
new KpiResourceTest().setupKpi();
|
||||
new BotResourceTest().setupBots();
|
||||
new QueryResourceTest().setupQuery(test);
|
||||
new DomainResourceTest().setupDomains(test);
|
||||
new DataProductResourceTest().setupDataProducts(test);
|
||||
|
||||
runWebhookTests = new Random().nextBoolean();
|
||||
if (runWebhookTests) {
|
||||
@ -577,7 +588,7 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
||||
int totalRecords = allEntities.getData().size();
|
||||
printEntities(allEntities);
|
||||
|
||||
// List entity with "limit" set from 1 to maxTables size with random jumps (to reduce the test time)
|
||||
// List entity with "limit" set from 1 to maxEntities size with random jumps (to reduce the test time)
|
||||
// Each time compare the returned list with allTables list to make sure right results are returned
|
||||
for (int limit = 1; limit < maxEntities; limit += random.nextInt(5) + 1) {
|
||||
String after = null;
|
||||
@ -588,7 +599,13 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
||||
ResultList<T> backwardPage;
|
||||
boolean foundDeleted = false;
|
||||
do { // For each limit (or page size) - forward scroll till the end
|
||||
LOG.debug("Limit {} forward scrollCount {} afterCursor {}", limit, pageCount, after);
|
||||
LOG.debug(
|
||||
"Limit {} forward pageCount {} indexInAllTables {} totalRecords {} afterCursor {}",
|
||||
limit,
|
||||
pageCount,
|
||||
indexInAllTables,
|
||||
totalRecords,
|
||||
after);
|
||||
forwardPage = listEntities(queryParams, limit, null, after, ADMIN_AUTH_HEADERS);
|
||||
foundDeleted = forwardPage.getData().stream().anyMatch(matchDeleted) || foundDeleted;
|
||||
after = forwardPage.getPaging().getAfter();
|
||||
@ -620,7 +637,13 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
||||
indexInAllTables = totalRecords - limit - forwardPage.getData().size();
|
||||
foundDeleted = false;
|
||||
do {
|
||||
LOG.debug("Limit {} backward scrollCount {} beforeCursor {}", limit, pageCount, before);
|
||||
LOG.debug(
|
||||
"Limit {} backward pageCount {} indexInAllTables {} totalRecords {} afterCursor {}",
|
||||
limit,
|
||||
pageCount,
|
||||
indexInAllTables,
|
||||
totalRecords,
|
||||
after);
|
||||
forwardPage = listEntities(queryParams, limit, before, null, ADMIN_AUTH_HEADERS);
|
||||
foundDeleted = forwardPage.getData().stream().anyMatch(matchDeleted) || foundDeleted;
|
||||
printEntities(forwardPage);
|
||||
|
@ -25,7 +25,6 @@ public class WorkflowResourceTest extends EntityResourceTest<Workflow, CreateWor
|
||||
|
||||
public WorkflowResourceTest() {
|
||||
super(Entity.WORKFLOW, Workflow.class, WorkflowList.class, "automations/workflows", WorkflowResource.FIELDS);
|
||||
supportsEmptyDescription = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,99 @@
|
||||
package org.openmetadata.service.resources.domains;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.openmetadata.common.utils.CommonUtil.listOf;
|
||||
import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS;
|
||||
import static org.openmetadata.service.util.TestUtils.assertEntityReferenceNames;
|
||||
import static org.openmetadata.service.util.TestUtils.assertListNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.http.client.HttpResponseException;
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
import org.openmetadata.schema.api.domains.CreateDataProduct;
|
||||
import org.openmetadata.schema.entity.domains.DataProduct;
|
||||
import org.openmetadata.schema.type.EntityReference;
|
||||
import org.openmetadata.service.Entity;
|
||||
import org.openmetadata.service.resources.EntityResourceTest;
|
||||
import org.openmetadata.service.resources.domains.DataProductResource.DataProductList;
|
||||
import org.openmetadata.service.util.JsonUtils;
|
||||
|
||||
public class DataProductResourceTest extends EntityResourceTest<DataProduct, CreateDataProduct> {
|
||||
public DataProductResourceTest() {
|
||||
super(Entity.DATA_PRODUCT, DataProduct.class, DataProductList.class, "dataProducts", DataProductResource.FIELDS);
|
||||
supportsFieldsQueryParam = false; // TODO
|
||||
supportsEmptyDescription = false;
|
||||
}
|
||||
|
||||
public void setupDataProducts(TestInfo test) throws HttpResponseException {
|
||||
DOMAIN_DATA_PRODUCT = createEntity(createRequest(getEntityName(test)), ADMIN_AUTH_HEADERS);
|
||||
SUB_DOMAIN_DATA_PRODUCT =
|
||||
createEntity(
|
||||
createRequest(getEntityName(test, 1)).withDomain(SUB_DOMAIN.getFullyQualifiedName()), ADMIN_AUTH_HEADERS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreateDataProduct createRequest(String name) {
|
||||
return new CreateDataProduct()
|
||||
.withName(name)
|
||||
.withDescription(name)
|
||||
.withDomain(DOMAIN.getFullyQualifiedName())
|
||||
.withExperts(listOf(USER1.getFullyQualifiedName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateCreatedEntity(
|
||||
DataProduct createdEntity, CreateDataProduct request, Map<String, String> authHeaders) {
|
||||
// Entity specific validation
|
||||
assertEquals(request.getDomain(), createdEntity.getDomain().getFullyQualifiedName());
|
||||
assertEntityReferenceNames(request.getExperts(), createdEntity.getExperts());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compareEntities(DataProduct expected, DataProduct updated, Map<String, String> authHeaders) {
|
||||
// Entity specific validation
|
||||
assertReference(expected.getDomain(), updated.getDomain());
|
||||
assertEntityReferences(expected.getExperts(), updated.getExperts());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataProduct validateGetWithDifferentFields(DataProduct dataProduct, boolean byName)
|
||||
throws HttpResponseException {
|
||||
DataProduct getDataProduct =
|
||||
byName
|
||||
? getEntityByName(dataProduct.getFullyQualifiedName(), null, ADMIN_AUTH_HEADERS)
|
||||
: getEntity(dataProduct.getId(), null, ADMIN_AUTH_HEADERS);
|
||||
assertListNull(getDataProduct.getOwner(), getDataProduct.getExperts());
|
||||
String fields = "owner,domain,experts";
|
||||
getDataProduct =
|
||||
byName
|
||||
? getEntityByName(getDataProduct.getFullyQualifiedName(), fields, ADMIN_AUTH_HEADERS)
|
||||
: getEntity(getDataProduct.getId(), fields, ADMIN_AUTH_HEADERS);
|
||||
// Fields requested are received
|
||||
assertReference(dataProduct.getDomain(), getDataProduct.getDomain());
|
||||
assertEntityReferences(dataProduct.getExperts(), getDataProduct.getExperts());
|
||||
|
||||
// Checks for other owner, tags, and followers is done in the base class
|
||||
return getDataProduct;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertFieldChange(String fieldName, Object expected, Object actual) throws IOException {
|
||||
if (expected == actual) {
|
||||
return;
|
||||
}
|
||||
if (fieldName.startsWith("domain")) {
|
||||
EntityReference expectedRef = (EntityReference) expected;
|
||||
EntityReference actualRef = JsonUtils.readValue(actual.toString(), EntityReference.class);
|
||||
assertEquals(expectedRef.getId(), actualRef.getId());
|
||||
} else if (fieldName.startsWith("experts")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<EntityReference> expectedRefs = (List<EntityReference>) expected;
|
||||
List<EntityReference> actualRefs = JsonUtils.readObjects(actual.toString(), EntityReference.class);
|
||||
assertEntityReferences(expectedRefs, actualRefs);
|
||||
} else {
|
||||
assertCommonFieldChange(fieldName, expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.http.client.HttpResponseException;
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
import org.openmetadata.schema.api.domains.CreateDomain;
|
||||
import org.openmetadata.schema.api.domains.CreateDomain.DomainType;
|
||||
import org.openmetadata.schema.entity.domains.Domain;
|
||||
@ -24,6 +25,13 @@ public class DomainResourceTest extends EntityResourceTest<Domain, CreateDomain>
|
||||
public DomainResourceTest() {
|
||||
super(Entity.DOMAIN, Domain.class, DomainList.class, "domains", DomainResource.FIELDS);
|
||||
supportsFieldsQueryParam = false; // TODO
|
||||
supportsEmptyDescription = false;
|
||||
}
|
||||
|
||||
public void setupDomains(TestInfo test) throws IOException {
|
||||
DOMAIN = createEntity(createRequest(test), ADMIN_AUTH_HEADERS);
|
||||
SUB_DOMAIN =
|
||||
createEntity(createRequest("sub-domain").withParent(DOMAIN.getFullyQualifiedName()), ADMIN_AUTH_HEADERS);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -31,6 +39,7 @@ public class DomainResourceTest extends EntityResourceTest<Domain, CreateDomain>
|
||||
return new CreateDomain()
|
||||
.withName(name)
|
||||
.withDomainType(DomainType.AGGREGATE)
|
||||
.withDescription("name")
|
||||
.withExperts(listOf(USER1.getFullyQualifiedName()));
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,6 @@ public class EventSubscriptionResourceTest extends EntityResourceTest<EventSubsc
|
||||
supportedNameCharacters = supportedNameCharacters.replace(" ", ""); // Space not supported
|
||||
supportsSoftDelete = false;
|
||||
supportsFieldsQueryParam = false;
|
||||
supportsEmptyDescription = true;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -91,12 +91,11 @@ public class GlossaryResourceTest extends EntityResourceTest<Glossary, CreateGlo
|
||||
}
|
||||
|
||||
public void setupGlossaries() throws IOException {
|
||||
GlossaryResourceTest glossaryResourceTest = new GlossaryResourceTest();
|
||||
CreateGlossary createGlossary = glossaryResourceTest.createRequest("g1", "", "", null);
|
||||
GLOSSARY1 = glossaryResourceTest.createEntity(createGlossary, ADMIN_AUTH_HEADERS);
|
||||
CreateGlossary createGlossary = createRequest("g1", "", "", null);
|
||||
GLOSSARY1 = createEntity(createGlossary, ADMIN_AUTH_HEADERS);
|
||||
|
||||
createGlossary = glossaryResourceTest.createRequest("g2", "", "", null);
|
||||
GLOSSARY2 = glossaryResourceTest.createEntity(createGlossary, ADMIN_AUTH_HEADERS);
|
||||
createGlossary = createRequest("g2", "", "", null);
|
||||
GLOSSARY2 = createEntity(createGlossary, ADMIN_AUTH_HEADERS);
|
||||
|
||||
GlossaryTermResourceTest glossaryTermResourceTest = new GlossaryTermResourceTest();
|
||||
CreateGlossaryTerm createGlossaryTerm =
|
||||
@ -532,11 +531,4 @@ public class GlossaryResourceTest extends EntityResourceTest<Glossary, CreateGlo
|
||||
assertTagPrefixAbsent(table.getColumns().get(0).getTags(), previousTermFqn);
|
||||
}
|
||||
}
|
||||
|
||||
private static String quoteName(String name) {
|
||||
if (name != null && !name.contains("\"")) {
|
||||
return name.contains(".") ? "\\\"" + name + "\\\"" : name;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,10 @@
|
||||
|
||||
package org.openmetadata.schema;
|
||||
|
||||
import java.util.List;
|
||||
import org.openmetadata.schema.type.EntityReference;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public interface CreateEntity {
|
||||
String getName();
|
||||
|
||||
@ -30,6 +32,14 @@ public interface CreateEntity {
|
||||
return null;
|
||||
}
|
||||
|
||||
default String getDomain() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default List<String> getDataProducts() {
|
||||
return null;
|
||||
}
|
||||
|
||||
<K extends CreateEntity> K withName(String name);
|
||||
|
||||
<K extends CreateEntity> K withDisplayName(String displayName);
|
||||
@ -43,4 +53,8 @@ public interface CreateEntity {
|
||||
default <K extends CreateEntity> K withExtension(Object extension) {
|
||||
return (K) this;
|
||||
}
|
||||
|
||||
default <K extends CreateEntity> K withDomain(String domain) {
|
||||
return (K) this;
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import org.openmetadata.schema.type.Votes;
|
||||
import org.openmetadata.schema.utils.EntityInterfaceUtil;
|
||||
|
||||
/** Interface to be implemented by all entities to provide a way to access all the common fields. */
|
||||
@SuppressWarnings("unused")
|
||||
public interface EntityInterface {
|
||||
// Lower case entity name to canonical entity name map
|
||||
Map<String, String> CANONICAL_ENTITY_NAME_MAP = new HashMap<>();
|
||||
@ -81,6 +82,14 @@ public interface EntityInterface {
|
||||
return null;
|
||||
}
|
||||
|
||||
default EntityReference getDomain() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default List<EntityReference> getDataProducts() {
|
||||
return null;
|
||||
}
|
||||
|
||||
void setId(UUID id);
|
||||
|
||||
void setDescription(String description);
|
||||
@ -115,6 +124,14 @@ public interface EntityInterface {
|
||||
/* no-op implementation to be overridden */
|
||||
}
|
||||
|
||||
default void setDomain(EntityReference entityReference) {
|
||||
/* no-op implementation to be overridden */
|
||||
}
|
||||
|
||||
default void setDataProducts(List<EntityReference> dataProducts) {
|
||||
/* no-op implementation to be overridden */
|
||||
}
|
||||
|
||||
<T extends EntityInterface> T withHref(URI href);
|
||||
|
||||
@JsonIgnore
|
||||
|
@ -41,6 +41,17 @@
|
||||
"service": {
|
||||
"description": "Link to the chart service where this chart is hosted in",
|
||||
"$ref": "../../type/basic.json#/definitions/fullyQualifiedEntityName"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Chart belongs to.",
|
||||
"$ref" : "../../type/basic.json#/definitions/fullyQualifiedEntityName"
|
||||
},
|
||||
"dataProducts" : {
|
||||
"description": "List of fully qualified names of data products this entity is part of.",
|
||||
"type": "array",
|
||||
"items" : {
|
||||
"$ref" : "../../type/basic.json#/definitions/fullyQualifiedEntityName"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["name", "service"],
|
||||
|
@ -71,6 +71,10 @@
|
||||
"extension": {
|
||||
"description": "Entity extension data with custom attributes added to the entity.",
|
||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Container belongs to.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "service"],
|
||||
|
@ -65,6 +65,17 @@
|
||||
"extension": {
|
||||
"description": "Entity extension data with custom attributes added to the entity.",
|
||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Dashboard belongs to.",
|
||||
"$ref" : "../../type/basic.json#/definitions/fullyQualifiedEntityName"
|
||||
},
|
||||
"dataProducts" : {
|
||||
"description": "List of fully qualified names of data products this entity is part of.",
|
||||
"type": "array",
|
||||
"items" : {
|
||||
"$ref" : "../../type/basic.json#/definitions/fullyQualifiedEntityName"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["name", "service"],
|
||||
|
@ -58,6 +58,10 @@
|
||||
"project": {
|
||||
"description": "Name of the project / workspace / collection in which the dataModel is contained",
|
||||
"type": "string"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Dashboard Data Model belongs to.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "service", "dataModelType", "columns"],
|
||||
|
@ -48,6 +48,10 @@
|
||||
"extension": {
|
||||
"description": "Entity extension data with custom attributes added to the entity.",
|
||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Database belongs to.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "service"],
|
||||
|
@ -44,6 +44,10 @@
|
||||
"extension": {
|
||||
"description": "Entity extension data with custom attributes added to the entity.",
|
||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Database Schema belongs to.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
@ -46,6 +46,10 @@
|
||||
"description" : "Glossary terms that are direct children in this glossary are mutually exclusive. When mutually exclusive is `true` only one term can be used to label an entity. When mutually exclusive is `false`, multiple terms from this group can be used to label an entity.",
|
||||
"type" : "boolean",
|
||||
"default" : "false"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Glossary belongs to.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "description"],
|
||||
|
@ -75,6 +75,10 @@
|
||||
"extension": {
|
||||
"description": "Entity extension data with custom attributes added to the entity.",
|
||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the MLModel belongs to.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "algorithm", "service"],
|
||||
|
@ -68,6 +68,10 @@
|
||||
"description": "Scheduler Interval for the pipeline in cron format.",
|
||||
"type": "string",
|
||||
"default": null
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Pipeline belongs to.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "service"],
|
||||
|
@ -77,6 +77,17 @@
|
||||
"sourceUrl": {
|
||||
"description": "Source URL of table.",
|
||||
"$ref": "../../type/basic.json#/definitions/sourceUrl"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Table belongs to.",
|
||||
"type": "string"
|
||||
},
|
||||
"dataProducts" : {
|
||||
"description": "List of fully qualified names of data products this entity is part of.",
|
||||
"type": "array",
|
||||
"items" : {
|
||||
"$ref" : "../../type/basic.json#/definitions/fullyQualifiedEntityName"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["name", "columns", "databaseSchema"],
|
||||
|
@ -79,6 +79,18 @@
|
||||
"extension": {
|
||||
"description": "Entity extension data with custom attributes added to the entity.",
|
||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Topic belongs to.",
|
||||
"type": "string",
|
||||
"$ref" : "../../type/basic.json#/definitions/fullyQualifiedEntityName"
|
||||
},
|
||||
"dataProducts" : {
|
||||
"description": "List of fully qualified names of data products this entity is part of.",
|
||||
"type": "array",
|
||||
"items" : {
|
||||
"$ref" : "../../type/basic.json#/definitions/fullyQualifiedEntityName"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["name", "service", "partitions"],
|
||||
|
@ -0,0 +1,47 @@
|
||||
{
|
||||
"$id": "https://open-metadata.org/schema/entity/domains/createDataProduct.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "createDataProduct",
|
||||
"description": "Create DataProduct API request",
|
||||
"type": "object",
|
||||
"javaType": "org.openmetadata.schema.api.domains.CreateDataProduct",
|
||||
"javaInterfaces": ["org.openmetadata.schema.CreateEntity"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "A unique name of the DataProduct",
|
||||
"$ref": "../../type/basic.json#/definitions/entityName"
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"description": "FullyQualifiedName of the Domain.",
|
||||
"$ref": "../../type/basic.json#/definitions/fullyQualifiedEntityName"
|
||||
},
|
||||
"displayName": {
|
||||
"description": "Name used for display purposes. Example 'Customer Churn', 'Sentiment Analysis', etc.",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "Description of the DataProduct.",
|
||||
"$ref": "../../type/basic.json#/definitions/markdown"
|
||||
},
|
||||
"owner": {
|
||||
"description": "Owner of this DataProduct.",
|
||||
"$ref": "../../type/entityReference.json",
|
||||
"default": null
|
||||
},
|
||||
"domain": {
|
||||
"description": "Fully qualified name of the Domain the DataProduct belongs to.",
|
||||
"$ref" : "../../type/basic.json#/definitions/fullyQualifiedEntityName",
|
||||
"default": null
|
||||
},
|
||||
"experts": {
|
||||
"description": "List of of user/login names of users who are experts in this DataProduct.",
|
||||
"type" : "array",
|
||||
"items": {
|
||||
"type" : "string"
|
||||
},
|
||||
"default": null
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "description", "domain","href"],
|
||||
"additionalProperties": false
|
||||
}
|
@ -45,6 +45,6 @@
|
||||
"default": null
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "domainType","href"],
|
||||
"required": ["id", "name", "description", "domainType","href"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
@ -36,6 +36,10 @@
|
||||
"owner": {
|
||||
"description": "Owner of this dashboard service.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Dashboard Service belongs to.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "serviceType", "connection"],
|
||||
|
@ -37,6 +37,10 @@
|
||||
"owner": {
|
||||
"description": "Owner of this database service.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Database Service belongs to.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "serviceType", "connection"],
|
||||
|
@ -37,6 +37,10 @@
|
||||
"owner": {
|
||||
"description": "Owner of this messaging service.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Messaging Service belongs to.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "serviceType", "connection"],
|
||||
|
@ -37,6 +37,10 @@
|
||||
"owner": {
|
||||
"description": "Owner of this mlModel service.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the MLModel Service belongs to.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "serviceType", "connection"],
|
||||
|
@ -42,6 +42,10 @@
|
||||
"description": "Scheduler Interval for the pipeline in cron format.",
|
||||
"type": "string",
|
||||
"default": null
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Pipeline Service belongs to.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "serviceType", "connection"],
|
||||
|
@ -37,6 +37,10 @@
|
||||
"owner": {
|
||||
"description": "Owner of this object store service.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Storage Service belongs to.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "serviceType", "connection"],
|
||||
|
@ -80,6 +80,10 @@
|
||||
"$ref": "../../type/basic.json#/definitions/uuid"
|
||||
},
|
||||
"default": null
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Fully qualified name of the domain the Team belongs to.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "teamType"],
|
||||
|
@ -138,6 +138,14 @@
|
||||
"description": "When `true` indicates the entity has been soft deleted.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Chart belongs to. The Chart inherits domain from the dashboard service it belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
},
|
||||
"dataProducts" : {
|
||||
"description": "List of of data products this entity is part of.",
|
||||
"$ref" : "../../type/entityReferenceList.json#/definitions/entityReferenceList"
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "service"],
|
||||
|
@ -167,6 +167,10 @@
|
||||
"extension": {
|
||||
"description": "Entity extension data with custom attributes added to the entity.",
|
||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Container belongs to. When not set, the Container inherits the domain from the storage service it belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
@ -126,6 +126,14 @@
|
||||
"extension": {
|
||||
"description": "Entity extension data with custom attributes added to the entity.",
|
||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Dashboard belongs to. When not set, the Dashboard inherits the domain from the dashboard service it belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
},
|
||||
"dataProducts" : {
|
||||
"description": "List of of data products this entity is part of.",
|
||||
"$ref" : "../../type/entityReferenceList.json#/definitions/entityReferenceList"
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "service"],
|
||||
|
@ -137,6 +137,10 @@
|
||||
"project": {
|
||||
"description": "Name of the project / workspace / collection in which the dataModel is contained",
|
||||
"type": "string"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Dashboard Data Model belongs to. When not set, the Dashboard model inherits the domain from the dashboard service it belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
@ -107,6 +107,10 @@
|
||||
"extension": {
|
||||
"description": "Entity extension data with custom attributes added to the entity.",
|
||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Database belongs to. When not set, the Database inherits the domain from the database service it belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"required": ["name", "service"],
|
||||
|
@ -102,6 +102,10 @@
|
||||
"extension": {
|
||||
"description": "Entity extension data with custom attributes added to the entity.",
|
||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Database Schema belongs to. When not set, the Schema inherits the domain from the database it belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"required": ["name", "database", "service"],
|
||||
|
@ -91,6 +91,10 @@
|
||||
"description" : "Glossary terms that are direct children in this glossary are mutually exclusive. When mutually exclusive is `true` only one term can be used to label an entity. When mutually exclusive is `false`, multiple terms from this group can be used to label an entity.",
|
||||
"type" : "boolean",
|
||||
"default" : "false"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Glossary belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "description"],
|
||||
|
@ -139,6 +139,10 @@
|
||||
"description" : "Glossary terms that are children of this term are mutually exclusive. When mutually exclusive is `true` only one term can be used to label an entity from this group. When mutually exclusive is `false`, multiple terms from this group can be used to label an entity.",
|
||||
"type" : "boolean",
|
||||
"default" : "false"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Glossary Term belongs to. When not set, the Glossary TErm inherits the domain from the Glossary it belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "description", "glossary"],
|
||||
|
@ -72,6 +72,10 @@
|
||||
"description": "When `true` indicates the entity has been soft deleted.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Metrics belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "service"],
|
||||
|
@ -264,7 +264,12 @@
|
||||
"extension": {
|
||||
"description": "Entity extension data with custom attributes added to the entity.",
|
||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the MLModel belongs to. When not set, the MLModel inherits the domain from the ML Model Service it belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
|
||||
},
|
||||
"required": ["id", "name", "algorithm", "service"],
|
||||
"additionalProperties": false
|
||||
|
@ -253,7 +253,12 @@
|
||||
"description": "Scheduler Interval for the pipeline in cron format.",
|
||||
"type": "string",
|
||||
"default": null
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Pipeline belongs to. When not set, the pipeline inherits the domain from the Pipeline service it belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
|
||||
},
|
||||
"required": ["id", "name", "service"],
|
||||
"additionalProperties": false
|
||||
|
@ -1006,6 +1006,14 @@
|
||||
"sourceUrl": {
|
||||
"description": "Source URL of table.",
|
||||
"$ref": "../../type/basic.json#/definitions/sourceUrl"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the table belongs to. When not set, the table inherits the domain from the database schema it belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
},
|
||||
"dataProducts" : {
|
||||
"description": "List of of data products this entity is part of.",
|
||||
"$ref" : "../../type/entityReferenceList.json#/definitions/entityReferenceList"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
@ -152,6 +152,14 @@
|
||||
"extension": {
|
||||
"description": "Entity extension data with custom attributes added to the entity.",
|
||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Topic belongs to. When not set, the Topic inherits the domain from the messaging service it belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
},
|
||||
"dataProducts" : {
|
||||
"description": "List of of data products this entity is part of.",
|
||||
"$ref" : "../../type/entityReferenceList.json#/definitions/entityReferenceList"
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "partitions", "service"],
|
||||
|
@ -0,0 +1,66 @@
|
||||
{
|
||||
"$id": "https://open-metadata.org/schema/entity/domains/dataProduct.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "DataProduct",
|
||||
"description": "A `Data Product` or `Data as a Product` is a logical unit that contains all components to process and store domain data for analytical or data-intensive use cases made available to data consumers.",
|
||||
"type": "object",
|
||||
"javaType": "org.openmetadata.schema.entity.domains.DataProduct",
|
||||
"javaInterfaces": ["org.openmetadata.schema.EntityInterface"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "Unique ID of the Data Product",
|
||||
"$ref": "../../type/basic.json#/definitions/uuid"
|
||||
},
|
||||
"name": {
|
||||
"description": "A unique name of the Data Product",
|
||||
"$ref": "../../type/basic.json#/definitions/entityName"
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"description": "FullyQualifiedName is `domain.dataProductName` or `sub-domain.dataProductName`.",
|
||||
"$ref": "../../type/basic.json#/definitions/fullyQualifiedEntityName"
|
||||
},
|
||||
"displayName": {
|
||||
"description": "Name used for display purposes. Example 'Marketing', 'Payments', etc.",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "Description of the Data Product.",
|
||||
"$ref": "../../type/basic.json#/definitions/markdown"
|
||||
},
|
||||
"version": {
|
||||
"description": "Metadata version of the entity.",
|
||||
"$ref": "../../type/entityHistory.json#/definitions/entityVersion"
|
||||
},
|
||||
"updatedAt": {
|
||||
"description": "Last update time corresponding to the new version of the entity in Unix epoch time milliseconds.",
|
||||
"$ref": "../../type/basic.json#/definitions/timestamp"
|
||||
},
|
||||
"updatedBy": {
|
||||
"description": "User who made the update.",
|
||||
"type": "string"
|
||||
},
|
||||
"href": {
|
||||
"description": "Link to the resource corresponding to this entity.",
|
||||
"$ref": "../../type/basic.json#/definitions/href"
|
||||
},
|
||||
"owner": {
|
||||
"description": "Owner of this Data Product.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
},
|
||||
"experts": {
|
||||
"description": "List of of users who are experts for this Data Product.",
|
||||
"$ref": "../../type/entityReferenceList.json#/definitions/entityReferenceList",
|
||||
"default" : null
|
||||
},
|
||||
"domain": {
|
||||
"description": "Domain or sub-domain to which this Data Product belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
},
|
||||
"changeDescription": {
|
||||
"description": "Change that lead to this version of the entity.",
|
||||
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "description", "domain", "href"],
|
||||
"additionalProperties": false
|
||||
}
|
@ -80,6 +80,6 @@
|
||||
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "domainType, ","href"],
|
||||
"required": ["id", "name", "description", "domainType, ","href"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
@ -178,6 +178,10 @@
|
||||
"description": "When `true` indicates the entity has been soft deleted.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Dashboard service belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "serviceType"],
|
||||
|
@ -332,6 +332,10 @@
|
||||
"description": "When `true` indicates the entity has been soft deleted.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Database service belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "serviceType"],
|
||||
|
@ -139,6 +139,10 @@
|
||||
"description": "When `true` indicates the entity has been soft deleted.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Messaging service belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "serviceType"],
|
||||
|
@ -131,6 +131,10 @@
|
||||
"description": "When `true` indicates the entity has been soft deleted.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the MLModel service belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "serviceType"],
|
||||
|
@ -180,6 +180,10 @@
|
||||
"description": "When `true` indicates the entity has been soft deleted.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Pipeline service belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
@ -121,6 +121,10 @@
|
||||
"description": "When `true` indicates the entity has been soft deleted.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Storage service belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "serviceType"],
|
||||
|
@ -123,6 +123,10 @@
|
||||
"policies": {
|
||||
"description": "Policies that is attached to this team.",
|
||||
"$ref": "../../type/entityReferenceList.json#/definitions/entityReferenceList"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the Team belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "href"],
|
||||
|
@ -132,6 +132,10 @@
|
||||
"isEmailVerified": {
|
||||
"description": "If the User has verified the mail",
|
||||
"type": "boolean"
|
||||
},
|
||||
"domain" : {
|
||||
"description": "Domain the User belongs to. This is inherited by the team the user belongs to.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
Loading…
x
Reference in New Issue
Block a user