mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-07-07 09:09:30 +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),
|
PRIMARY KEY (id),
|
||||||
UNIQUE (fqnHash)
|
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),
|
PRIMARY KEY (id),
|
||||||
UNIQUE (fqnHash)
|
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_DISPLAY_NAME = "displayName";
|
||||||
public static final String FIELD_EXTENSION = "extension";
|
public static final String FIELD_EXTENSION = "extension";
|
||||||
public static final String FIELD_USAGE_SUMMARY = "usageSummary";
|
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
|
// Service entities
|
||||||
@ -132,6 +134,7 @@ public final class Entity {
|
|||||||
// Domain related entities
|
// Domain related entities
|
||||||
//
|
//
|
||||||
public static final String DOMAIN = "domain";
|
public static final String DOMAIN = "domain";
|
||||||
|
public static final String DATA_PRODUCT = "dataProduct";
|
||||||
|
|
||||||
//
|
//
|
||||||
// Reserved names in OpenMetadata
|
// 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.Report;
|
||||||
import org.openmetadata.schema.entity.data.Table;
|
import org.openmetadata.schema.entity.data.Table;
|
||||||
import org.openmetadata.schema.entity.data.Topic;
|
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.domains.Domain;
|
||||||
import org.openmetadata.schema.entity.events.EventSubscription;
|
import org.openmetadata.schema.entity.events.EventSubscription;
|
||||||
import org.openmetadata.schema.entity.policies.Policy;
|
import org.openmetadata.schema.entity.policies.Policy;
|
||||||
@ -198,6 +199,9 @@ public interface CollectionDAO {
|
|||||||
@CreateSqlObject
|
@CreateSqlObject
|
||||||
DomainDAO domainDAO();
|
DomainDAO domainDAO();
|
||||||
|
|
||||||
|
@CreateSqlObject
|
||||||
|
DataProductDAO dataProductDAO();
|
||||||
|
|
||||||
@CreateSqlObject
|
@CreateSqlObject
|
||||||
EventSubscriptionDAO eventSubscriptionDAO();
|
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> {
|
interface EventSubscriptionDAO extends EntityDAO<EventSubscription> {
|
||||||
@Override
|
@Override
|
||||||
default String getTableName() {
|
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
|
@Slf4j
|
||||||
public class DomainRepository extends EntityRepository<Domain> {
|
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) {
|
public DomainRepository(CollectionDAO dao) {
|
||||||
super(
|
super(
|
||||||
@ -50,8 +50,7 @@ public class DomainRepository extends EntityRepository<Domain> {
|
|||||||
public Domain setFields(Domain entity, Fields fields) throws IOException {
|
public Domain setFields(Domain entity, Fields fields) throws IOException {
|
||||||
entity.withParent(fields.contains("parent") ? getParent(entity) : null);
|
entity.withParent(fields.contains("parent") ? getParent(entity) : null);
|
||||||
entity.withChildren(fields.contains("children") ? getChildren(entity) : null);
|
entity.withChildren(fields.contains("children") ? getChildren(entity) : null);
|
||||||
entity.withExperts(fields.contains("experts") ? getExperts(entity) : null);
|
return entity.withExperts(fields.contains("experts") ? getExperts(entity) : null);
|
||||||
return entity.withOwner(fields.contains("owner") ? getOwner(entity) : null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private EntityReference getParent(Domain entity) throws IOException {
|
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.DELETED;
|
||||||
import static org.openmetadata.schema.type.Include.NON_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.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_DELETED;
|
||||||
import static org.openmetadata.service.Entity.FIELD_DESCRIPTION;
|
import static org.openmetadata.service.Entity.FIELD_DESCRIPTION;
|
||||||
import static org.openmetadata.service.Entity.FIELD_DISPLAY_NAME;
|
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_EXTENSION;
|
||||||
import static org.openmetadata.service.Entity.FIELD_FOLLOWERS;
|
import static org.openmetadata.service.Entity.FIELD_FOLLOWERS;
|
||||||
import static org.openmetadata.service.Entity.FIELD_OWNER;
|
import static org.openmetadata.service.Entity.FIELD_OWNER;
|
||||||
@ -163,6 +167,8 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
|||||||
@Getter protected final boolean supportsOwner;
|
@Getter protected final boolean supportsOwner;
|
||||||
protected final boolean supportsFollower;
|
protected final boolean supportsFollower;
|
||||||
protected final boolean supportsVotes;
|
protected final boolean supportsVotes;
|
||||||
|
protected final boolean supportsDomain;
|
||||||
|
protected final boolean supportsDataProducts;
|
||||||
|
|
||||||
/** Fields that can be updated during PATCH operation */
|
/** Fields that can be updated during PATCH operation */
|
||||||
@Getter private final Fields patchFields;
|
@Getter private final Fields patchFields;
|
||||||
@ -192,6 +198,8 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
|||||||
this.supportsSoftDelete = allowedFields.contains(FIELD_DELETED);
|
this.supportsSoftDelete = allowedFields.contains(FIELD_DELETED);
|
||||||
this.supportsFollower = allowedFields.contains(FIELD_FOLLOWERS);
|
this.supportsFollower = allowedFields.contains(FIELD_FOLLOWERS);
|
||||||
this.supportsVotes = allowedFields.contains(FIELD_VOTES);
|
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);
|
prepare(entity);
|
||||||
setFullyQualifiedName(entity);
|
setFullyQualifiedName(entity);
|
||||||
validateExtension(entity);
|
validateExtension(entity);
|
||||||
|
// Domain is already validated
|
||||||
}
|
}
|
||||||
|
|
||||||
public void storeRelationshipsInternal(T entity) throws IOException {
|
public void storeRelationshipsInternal(T entity) throws IOException {
|
||||||
storeOwner(entity, entity.getOwner());
|
storeOwner(entity, entity.getOwner());
|
||||||
applyTags(entity);
|
applyTags(entity);
|
||||||
|
storeDomain(entity, entity.getDomain());
|
||||||
|
storeDataProducts(entity, entity.getDataProducts());
|
||||||
storeRelationships(entity);
|
storeRelationships(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,6 +570,8 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
|||||||
entity.setOwner(fields.contains(FIELD_OWNER) ? getOwner(entity) : null);
|
entity.setOwner(fields.contains(FIELD_OWNER) ? getOwner(entity) : null);
|
||||||
entity.setTags(fields.contains(FIELD_TAGS) ? getTags(entity.getFullyQualifiedName()) : null);
|
entity.setTags(fields.contains(FIELD_TAGS) ? getTags(entity.getFullyQualifiedName()) : null);
|
||||||
entity.setExtension(fields.contains(FIELD_EXTENSION) ? getExtension(entity) : 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);
|
setFields(entity, fields);
|
||||||
setInheritedFields(entity);
|
setInheritedFields(entity);
|
||||||
return entity;
|
return entity;
|
||||||
@ -901,6 +914,10 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
|||||||
entity.setOwner(null);
|
entity.setOwner(null);
|
||||||
List<TagLabel> tags = entity.getTags();
|
List<TagLabel> tags = entity.getTags();
|
||||||
entity.setTags(null);
|
entity.setTags(null);
|
||||||
|
EntityReference domain = entity.getDomain();
|
||||||
|
entity.setDomain(null);
|
||||||
|
List<EntityReference> dataProducts = entity.getDataProducts();
|
||||||
|
entity.setDataProducts(null);
|
||||||
|
|
||||||
if (update) {
|
if (update) {
|
||||||
dao.update(entity.getId(), getFullyQualifiedNameHash(entity), JsonUtils.pojoToJson(entity));
|
dao.update(entity.getId(), getFullyQualifiedNameHash(entity), JsonUtils.pojoToJson(entity));
|
||||||
@ -913,6 +930,8 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
|||||||
// Restore the relationships
|
// Restore the relationships
|
||||||
entity.setOwner(owner);
|
entity.setOwner(owner);
|
||||||
entity.setTags(tags);
|
entity.setTags(tags);
|
||||||
|
entity.setDomain(domain);
|
||||||
|
entity.setDataProducts(dataProducts);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void storeTimeSeries(
|
protected void storeTimeSeries(
|
||||||
@ -990,7 +1009,7 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
|||||||
daoCollection.entityExtensionTimeSeriesDao().deleteBeforeTimestamp(fqnHash, extension, timestamp);
|
daoCollection.entityExtensionTimeSeriesDao().deleteBeforeTimestamp(fqnHash, extension, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validateExtension(T entity) {
|
private void validateExtension(T entity) {
|
||||||
if (entity.getExtension() == null) {
|
if (entity.getExtension() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1357,6 +1376,18 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
|||||||
return !supportsOwner ? null : getFromEntityRef(entity.getId(), Relationship.OWNS, null, false);
|
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 {
|
public EntityReference getOwner(EntityReference ref) throws IOException {
|
||||||
return !supportsOwner ? null : Entity.getEntityReferenceById(ref.getType(), ref.getId(), ALL);
|
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) {
|
protected void storeOwner(T entity, EntityReference owner) {
|
||||||
if (supportsOwner && owner != null) {
|
if (supportsOwner && owner != null) {
|
||||||
// Add relationship owner --- owns ---> ownedEntity
|
// 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);
|
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 */
|
/** Remove owner relationship for a given entity */
|
||||||
private void removeOwner(T entity, EntityReference owner) {
|
private void removeOwner(T entity, EntityReference owner) {
|
||||||
if (EntityUtil.getId(owner) != null) {
|
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);
|
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);
|
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 */
|
/** Override this method to support downloading CSV functionality */
|
||||||
public String exportToCsv(String name, String user) throws IOException {
|
public String exportToCsv(String name, String user) throws IOException {
|
||||||
throw new IllegalArgumentException(csvNotSupported(entityType));
|
throw new IllegalArgumentException(csvNotSupported(entityType));
|
||||||
@ -1531,6 +1593,8 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
|||||||
updateOwner();
|
updateOwner();
|
||||||
updateExtension();
|
updateExtension();
|
||||||
updateTags(updated.getFullyQualifiedName(), FIELD_TAGS, original.getTags(), updated.getTags());
|
updateTags(updated.getFullyQualifiedName(), FIELD_TAGS, original.getTags(), updated.getTags());
|
||||||
|
updateDomain();
|
||||||
|
updateDataProducts();
|
||||||
entitySpecificUpdate();
|
entitySpecificUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1664,6 +1728,47 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
|||||||
storeExtension(updated);
|
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) {
|
public final boolean updateVersion(Double oldVersion) {
|
||||||
Double newVersion = oldVersion;
|
Double newVersion = oldVersion;
|
||||||
if (majorVersionChange) {
|
if (majorVersionChange) {
|
||||||
|
@ -217,7 +217,6 @@ public abstract class EntityResource<T extends EntityInterface, K extends Entity
|
|||||||
OperationContext operationContext = new OperationContext(entityType, CREATE);
|
OperationContext operationContext = new OperationContext(entityType, CREATE);
|
||||||
authorizer.authorize(securityContext, operationContext, getResourceContext());
|
authorizer.authorize(securityContext, operationContext, getResourceContext());
|
||||||
entity = addHref(uriInfo, repository.create(uriInfo, entity));
|
entity = addHref(uriInfo, repository.create(uriInfo, entity));
|
||||||
LOG.info("Created {}:{}", Entity.getEntityTypeFromObject(entity), entity.getId());
|
|
||||||
return Response.created(entity.getHref()).entity(entity).build();
|
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 {
|
public T copy(T entity, CreateEntity request, String updatedBy) throws IOException {
|
||||||
EntityReference owner = repository.validateOwner(request.getOwner());
|
EntityReference owner = repository.validateOwner(request.getOwner());
|
||||||
|
EntityReference domain = repository.validateDomain(request.getDomain());
|
||||||
entity.setId(UUID.randomUUID());
|
entity.setId(UUID.randomUUID());
|
||||||
entity.setName(request.getName());
|
entity.setName(request.getName());
|
||||||
entity.setDisplayName(request.getDisplayName());
|
entity.setDisplayName(request.getDisplayName());
|
||||||
entity.setDescription(request.getDescription());
|
entity.setDescription(request.getDescription());
|
||||||
entity.setOwner(owner);
|
entity.setOwner(owner);
|
||||||
|
entity.setDomain(domain);
|
||||||
|
entity.setDataProducts(getEntityReferences(Entity.DATA_PRODUCT, request.getDataProducts()));
|
||||||
entity.setExtension(request.getExtension());
|
entity.setExtension(request.getExtension());
|
||||||
entity.setUpdatedBy(updatedBy);
|
entity.setUpdatedBy(updatedBy);
|
||||||
entity.setUpdatedAt(System.currentTimeMillis());
|
entity.setUpdatedAt(System.currentTimeMillis());
|
||||||
|
@ -73,7 +73,7 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
@Collection(name = "charts")
|
@Collection(name = "charts")
|
||||||
public class ChartResource extends EntityResource<Chart, ChartRepository> {
|
public class ChartResource extends EntityResource<Chart, ChartRepository> {
|
||||||
public static final String COLLECTION_PATH = "v1/charts/";
|
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
|
@Override
|
||||||
public Chart addHref(UriInfo uriInfo, Chart chart) {
|
public Chart addHref(UriInfo uriInfo, Chart chart) {
|
||||||
|
@ -73,7 +73,8 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
@Collection(name = "dashboards")
|
@Collection(name = "dashboards")
|
||||||
public class DashboardResource extends EntityResource<Dashboard, DashboardRepository> {
|
public class DashboardResource extends EntityResource<Dashboard, DashboardRepository> {
|
||||||
public static final String COLLECTION_PATH = "v1/dashboards/";
|
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
|
@Override
|
||||||
public Dashboard addHref(UriInfo uriInfo, Dashboard dashboard) {
|
public Dashboard addHref(UriInfo uriInfo, Dashboard dashboard) {
|
||||||
|
@ -71,7 +71,7 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
@Collection(name = "databases")
|
@Collection(name = "databases")
|
||||||
public class DatabaseResource extends EntityResource<Database, DatabaseRepository> {
|
public class DatabaseResource extends EntityResource<Database, DatabaseRepository> {
|
||||||
public static final String COLLECTION_PATH = "v1/databases/";
|
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
|
@Override
|
||||||
public Database addHref(UriInfo uriInfo, Database db) {
|
public Database addHref(UriInfo uriInfo, Database db) {
|
||||||
|
@ -71,7 +71,7 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
@Collection(name = "databaseSchemas")
|
@Collection(name = "databaseSchemas")
|
||||||
public class DatabaseSchemaResource extends EntityResource<DatabaseSchema, DatabaseSchemaRepository> {
|
public class DatabaseSchemaResource extends EntityResource<DatabaseSchema, DatabaseSchemaRepository> {
|
||||||
public static final String COLLECTION_PATH = "v1/databaseSchemas/";
|
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
|
@Override
|
||||||
public DatabaseSchema addHref(UriInfo uriInfo, DatabaseSchema schema) {
|
public DatabaseSchema addHref(UriInfo uriInfo, DatabaseSchema schema) {
|
||||||
|
@ -84,6 +84,9 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
@Collection(name = "tables")
|
@Collection(name = "tables")
|
||||||
public class TableResource extends EntityResource<Table, TableRepository> {
|
public class TableResource extends EntityResource<Table, TableRepository> {
|
||||||
public static final String COLLECTION_PATH = "v1/tables/";
|
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
|
@Override
|
||||||
public Table addHref(UriInfo uriInfo, Table table) {
|
public Table addHref(UriInfo uriInfo, Table table) {
|
||||||
@ -136,10 +139,6 @@ public class TableResource extends EntityResource<Table, TableRepository> {
|
|||||||
/* Required for serde */
|
/* Required for serde */
|
||||||
}
|
}
|
||||||
|
|
||||||
static final String FIELDS =
|
|
||||||
"tableConstraints,tablePartition,usageSummary,owner,customMetrics,"
|
|
||||||
+ "tags,followers,joins,viewDefinition,dataModel,extension,testSuite";
|
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Operation(
|
@Operation(
|
||||||
operationId = "listTables",
|
operationId = "listTables",
|
||||||
|
@ -70,7 +70,7 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
@Collection(name = "datamodels")
|
@Collection(name = "datamodels")
|
||||||
public class DashboardDataModelResource extends EntityResource<DashboardDataModel, DashboardDataModelRepository> {
|
public class DashboardDataModelResource extends EntityResource<DashboardDataModel, DashboardDataModelRepository> {
|
||||||
public static final String COLLECTION_PATH = "/v1/dashboard/datamodels";
|
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
|
@Override
|
||||||
public DashboardDataModel addHref(UriInfo uriInfo, DashboardDataModel dashboardDataModel) {
|
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.api.domains.CreateDomain;
|
||||||
import org.openmetadata.schema.entity.domains.Domain;
|
import org.openmetadata.schema.entity.domains.Domain;
|
||||||
import org.openmetadata.schema.type.EntityHistory;
|
import org.openmetadata.schema.type.EntityHistory;
|
||||||
|
import org.openmetadata.schema.type.Include;
|
||||||
import org.openmetadata.schema.utils.EntityInterfaceUtil;
|
import org.openmetadata.schema.utils.EntityInterfaceUtil;
|
||||||
import org.openmetadata.service.Entity;
|
import org.openmetadata.service.Entity;
|
||||||
import org.openmetadata.service.jdbi3.CollectionDAO;
|
import org.openmetadata.service.jdbi3.CollectionDAO;
|
||||||
@ -332,7 +333,8 @@ public class DomainResource extends EntityResource<Domain, DomainRepository> {
|
|||||||
return copy(new Domain(), create, user)
|
return copy(new Domain(), create, user)
|
||||||
.withDomainType(create.getDomainType())
|
.withDomainType(create.getDomainType())
|
||||||
.withFullyQualifiedName(create.getName())
|
.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)));
|
.withExperts(EntityUtil.populateEntityReferences(getEntityReferences(Entity.USER, experts)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,7 +339,6 @@ public class TestCaseResource extends EntityResource<TestCase, TestCaseRepositor
|
|||||||
authorizer.authorize(securityContext, operationContext, resourceContext);
|
authorizer.authorize(securityContext, operationContext, resourceContext);
|
||||||
repository.isTestSuiteExecutable(create.getTestSuite());
|
repository.isTestSuiteExecutable(create.getTestSuite());
|
||||||
test = addHref(uriInfo, repository.create(uriInfo, test));
|
test = addHref(uriInfo, repository.create(uriInfo, test));
|
||||||
LOG.info("Created {}:{}", Entity.getEntityTypeFromObject(test), test.getId());
|
|
||||||
return Response.created(test.getHref()).entity(test).build();
|
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
|
@Collection(name = "glossaries", order = 6) // Initialize before GlossaryTerm and after Classification and Tags
|
||||||
public class GlossaryResource extends EntityResource<Glossary, GlossaryRepository> {
|
public class GlossaryResource extends EntityResource<Glossary, GlossaryRepository> {
|
||||||
public static final String COLLECTION_PATH = "v1/glossaries/";
|
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
|
@Override
|
||||||
public Glossary addHref(UriInfo uriInfo, Glossary glossary) {
|
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
|
@Collection(name = "glossaryTerms", order = 7) // Initialized after Glossary, Classification, and Tags
|
||||||
public class GlossaryTermResource extends EntityResource<GlossaryTerm, GlossaryTermRepository> {
|
public class GlossaryTermResource extends EntityResource<GlossaryTerm, GlossaryTermRepository> {
|
||||||
public static final String COLLECTION_PATH = "v1/glossaryTerms/";
|
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
|
@Override
|
||||||
public GlossaryTerm addHref(UriInfo uriInfo, GlossaryTerm term) {
|
public GlossaryTerm addHref(UriInfo uriInfo, GlossaryTerm term) {
|
||||||
|
@ -63,7 +63,7 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
@Collection(name = "metrics")
|
@Collection(name = "metrics")
|
||||||
public class MetricsResource extends EntityResource<Metrics, MetricsRepository> {
|
public class MetricsResource extends EntityResource<Metrics, MetricsRepository> {
|
||||||
public static final String COLLECTION_PATH = "/v1/metrics/";
|
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) {
|
public MetricsResource(CollectionDAO dao, Authorizer authorizer) {
|
||||||
super(Metrics.class, new MetricsRepository(dao), authorizer);
|
super(Metrics.class, new MetricsRepository(dao), authorizer);
|
||||||
|
@ -73,7 +73,7 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
@Collection(name = "mlmodels")
|
@Collection(name = "mlmodels")
|
||||||
public class MlModelResource extends EntityResource<MlModel, MlModelRepository> {
|
public class MlModelResource extends EntityResource<MlModel, MlModelRepository> {
|
||||||
public static final String COLLECTION_PATH = "v1/mlmodels/";
|
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
|
@Override
|
||||||
public MlModel addHref(UriInfo uriInfo, MlModel mlmodel) {
|
public MlModel addHref(UriInfo uriInfo, MlModel mlmodel) {
|
||||||
|
@ -78,7 +78,7 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
@Collection(name = "pipelines")
|
@Collection(name = "pipelines")
|
||||||
public class PipelineResource extends EntityResource<Pipeline, PipelineRepository> {
|
public class PipelineResource extends EntityResource<Pipeline, PipelineRepository> {
|
||||||
public static final String COLLECTION_PATH = "v1/pipelines/";
|
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
|
@Override
|
||||||
public Pipeline addHref(UriInfo uriInfo, Pipeline pipeline) {
|
public Pipeline addHref(UriInfo uriInfo, Pipeline pipeline) {
|
||||||
|
@ -13,8 +13,6 @@
|
|||||||
|
|
||||||
package org.openmetadata.service.resources.services.dashboard;
|
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.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;
|
||||||
@ -79,7 +77,7 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
public class DashboardServiceResource
|
public class DashboardServiceResource
|
||||||
extends ServiceEntityResource<DashboardService, DashboardServiceRepository, DashboardConnection> {
|
extends ServiceEntityResource<DashboardService, DashboardServiceRepository, DashboardConnection> {
|
||||||
public static final String COLLECTION_PATH = "v1/services/dashboardServices";
|
public static final String COLLECTION_PATH = "v1/services/dashboardServices";
|
||||||
static final String FIELDS = FIELD_OWNER;
|
static final String FIELDS = "owner,domain";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DashboardService addHref(UriInfo uriInfo, DashboardService service) {
|
public DashboardService addHref(UriInfo uriInfo, DashboardService service) {
|
||||||
|
@ -83,7 +83,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,tags";
|
static final String FIELDS = "pipelines,owner,tags,domain";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DatabaseService addHref(UriInfo uriInfo, DatabaseService service) {
|
public DatabaseService addHref(UriInfo uriInfo, DatabaseService service) {
|
||||||
|
@ -13,8 +13,6 @@
|
|||||||
|
|
||||||
package org.openmetadata.service.resources.services.messaging;
|
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.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;
|
||||||
@ -79,7 +77,7 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
public class MessagingServiceResource
|
public class MessagingServiceResource
|
||||||
extends ServiceEntityResource<MessagingService, MessagingServiceRepository, MessagingConnection> {
|
extends ServiceEntityResource<MessagingService, MessagingServiceRepository, MessagingConnection> {
|
||||||
public static final String COLLECTION_PATH = "v1/services/messagingServices/";
|
public static final String COLLECTION_PATH = "v1/services/messagingServices/";
|
||||||
public static final String FIELDS = FIELD_OWNER;
|
public static final String FIELDS = "owner,domain";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MessagingService addHref(UriInfo uriInfo, MessagingService service) {
|
public MessagingService addHref(UriInfo uriInfo, MessagingService service) {
|
||||||
|
@ -79,7 +79,7 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
public class MlModelServiceResource
|
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,tags";
|
public static final String FIELDS = "pipelines,owner,tags,domain";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MlModelService addHref(UriInfo uriInfo, MlModelService service) {
|
public MlModelService addHref(UriInfo uriInfo, MlModelService service) {
|
||||||
|
@ -77,7 +77,7 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
public class PipelineServiceResource
|
public class PipelineServiceResource
|
||||||
extends ServiceEntityResource<PipelineService, PipelineServiceRepository, PipelineConnection> {
|
extends ServiceEntityResource<PipelineService, PipelineServiceRepository, PipelineConnection> {
|
||||||
public static final String COLLECTION_PATH = "v1/services/pipelineServices/";
|
public static final String COLLECTION_PATH = "v1/services/pipelineServices/";
|
||||||
static final String FIELDS = "pipelines,owner";
|
static final String FIELDS = "pipelines,owner,domain";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PipelineService addHref(UriInfo uriInfo, PipelineService service) {
|
public PipelineService addHref(UriInfo uriInfo, PipelineService service) {
|
||||||
|
@ -69,7 +69,7 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
public class StorageServiceResource
|
public class StorageServiceResource
|
||||||
extends ServiceEntityResource<StorageService, StorageServiceRepository, StorageConnection> {
|
extends ServiceEntityResource<StorageService, StorageServiceRepository, StorageConnection> {
|
||||||
public static final String COLLECTION_PATH = "v1/services/storageServices/";
|
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
|
@Override
|
||||||
public StorageService addHref(UriInfo uriInfo, StorageService service) {
|
public StorageService addHref(UriInfo uriInfo, StorageService service) {
|
||||||
|
@ -61,7 +61,7 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
@Collection(name = "containers")
|
@Collection(name = "containers")
|
||||||
public class ContainerResource extends EntityResource<Container, ContainerRepository> {
|
public class ContainerResource extends EntityResource<Container, ContainerRepository> {
|
||||||
public static final String COLLECTION_PATH = "v1/containers/";
|
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
|
@Override
|
||||||
public Container addHref(UriInfo uriInfo, Container container) {
|
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
|
@Collection(name = "teams", order = 2) // Load after roles, and policy resources
|
||||||
public class TeamResource extends EntityResource<Team, TeamRepository> {
|
public class TeamResource extends EntityResource<Team, TeamRepository> {
|
||||||
public static final String COLLECTION_PATH = "/v1/teams/";
|
public static final String COLLECTION_PATH = "/v1/teams/";
|
||||||
|
static final String FIELDS =
|
||||||
|
"owner,profile,users,owns,defaultRoles,parents,children,policies,userCount,childrenCount,domain";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Team addHref(UriInfo uriInfo, Team team) {
|
public Team addHref(UriInfo uriInfo, Team team) {
|
||||||
@ -122,9 +124,6 @@ public class TeamResource extends EntityResource<Team, TeamRepository> {
|
|||||||
/* Required for serde */
|
/* Required for serde */
|
||||||
}
|
}
|
||||||
|
|
||||||
static final String FIELDS =
|
|
||||||
"owner,profile,users,owns,defaultRoles,parents,children,policies,userCount,childrenCount";
|
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/hierarchy")
|
@Path("/hierarchy")
|
||||||
@Valid
|
@Valid
|
||||||
|
@ -159,7 +159,7 @@ public class UserResource extends EntityResource<User, UserRepository> {
|
|||||||
private boolean isEmailServiceEnabled;
|
private boolean isEmailServiceEnabled;
|
||||||
private AuthenticationConfiguration authenticationConfiguration;
|
private AuthenticationConfiguration authenticationConfiguration;
|
||||||
private final AuthenticatorHandler authHandler;
|
private final AuthenticatorHandler authHandler;
|
||||||
static final String FIELDS = "profile,roles,teams,follows,owns";
|
static final String FIELDS = "profile,roles,teams,follows,owns,domain";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User addHref(UriInfo uriInfo, User user) {
|
public User addHref(UriInfo uriInfo, User user) {
|
||||||
|
@ -77,7 +77,7 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
@Collection(name = "topics")
|
@Collection(name = "topics")
|
||||||
public class TopicResource extends EntityResource<Topic, TopicRepository> {
|
public class TopicResource extends EntityResource<Topic, TopicRepository> {
|
||||||
public static final String COLLECTION_PATH = "v1/topics/";
|
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
|
@Override
|
||||||
public Topic addHref(UriInfo uriInfo, Topic topic) {
|
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.Glossary;
|
||||||
import org.openmetadata.schema.entity.data.GlossaryTerm;
|
import org.openmetadata.schema.entity.data.GlossaryTerm;
|
||||||
import org.openmetadata.schema.entity.data.Table;
|
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.Policy;
|
||||||
import org.openmetadata.schema.entity.policies.accessControl.Rule;
|
import org.openmetadata.schema.entity.policies.accessControl.Rule;
|
||||||
import org.openmetadata.schema.entity.services.connections.TestConnectionResult;
|
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.exception.CatalogExceptionMessage;
|
||||||
import org.openmetadata.service.resources.bots.BotResourceTest;
|
import org.openmetadata.service.resources.bots.BotResourceTest;
|
||||||
import org.openmetadata.service.resources.databases.TableResourceTest;
|
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.TestCaseResourceTest;
|
||||||
import org.openmetadata.service.resources.dqtests.TestDefinitionResourceTest;
|
import org.openmetadata.service.resources.dqtests.TestDefinitionResourceTest;
|
||||||
import org.openmetadata.service.resources.dqtests.TestSuiteResourceTest;
|
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 final String C4 = "\"c.4\"";
|
||||||
public static List<Column> COLUMNS;
|
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 =
|
public static final TestConnectionResult TEST_CONNECTION_RESULT =
|
||||||
new TestConnectionResult()
|
new TestConnectionResult()
|
||||||
.withStatus(TestConnectionResultStatus.SUCCESSFUL)
|
.withStatus(TestConnectionResultStatus.SUCCESSFUL)
|
||||||
@ -405,6 +414,8 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
|||||||
new KpiResourceTest().setupKpi();
|
new KpiResourceTest().setupKpi();
|
||||||
new BotResourceTest().setupBots();
|
new BotResourceTest().setupBots();
|
||||||
new QueryResourceTest().setupQuery(test);
|
new QueryResourceTest().setupQuery(test);
|
||||||
|
new DomainResourceTest().setupDomains(test);
|
||||||
|
new DataProductResourceTest().setupDataProducts(test);
|
||||||
|
|
||||||
runWebhookTests = new Random().nextBoolean();
|
runWebhookTests = new Random().nextBoolean();
|
||||||
if (runWebhookTests) {
|
if (runWebhookTests) {
|
||||||
@ -577,7 +588,7 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
|||||||
int totalRecords = allEntities.getData().size();
|
int totalRecords = allEntities.getData().size();
|
||||||
printEntities(allEntities);
|
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
|
// 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) {
|
for (int limit = 1; limit < maxEntities; limit += random.nextInt(5) + 1) {
|
||||||
String after = null;
|
String after = null;
|
||||||
@ -588,7 +599,13 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
|||||||
ResultList<T> backwardPage;
|
ResultList<T> backwardPage;
|
||||||
boolean foundDeleted = false;
|
boolean foundDeleted = false;
|
||||||
do { // For each limit (or page size) - forward scroll till the end
|
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);
|
forwardPage = listEntities(queryParams, limit, null, after, ADMIN_AUTH_HEADERS);
|
||||||
foundDeleted = forwardPage.getData().stream().anyMatch(matchDeleted) || foundDeleted;
|
foundDeleted = forwardPage.getData().stream().anyMatch(matchDeleted) || foundDeleted;
|
||||||
after = forwardPage.getPaging().getAfter();
|
after = forwardPage.getPaging().getAfter();
|
||||||
@ -620,7 +637,13 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
|||||||
indexInAllTables = totalRecords - limit - forwardPage.getData().size();
|
indexInAllTables = totalRecords - limit - forwardPage.getData().size();
|
||||||
foundDeleted = false;
|
foundDeleted = false;
|
||||||
do {
|
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);
|
forwardPage = listEntities(queryParams, limit, before, null, ADMIN_AUTH_HEADERS);
|
||||||
foundDeleted = forwardPage.getData().stream().anyMatch(matchDeleted) || foundDeleted;
|
foundDeleted = forwardPage.getData().stream().anyMatch(matchDeleted) || foundDeleted;
|
||||||
printEntities(forwardPage);
|
printEntities(forwardPage);
|
||||||
|
@ -25,7 +25,6 @@ public class WorkflowResourceTest extends EntityResourceTest<Workflow, CreateWor
|
|||||||
|
|
||||||
public WorkflowResourceTest() {
|
public WorkflowResourceTest() {
|
||||||
super(Entity.WORKFLOW, Workflow.class, WorkflowList.class, "automations/workflows", WorkflowResource.FIELDS);
|
super(Entity.WORKFLOW, Workflow.class, WorkflowList.class, "automations/workflows", WorkflowResource.FIELDS);
|
||||||
supportsEmptyDescription = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.apache.http.client.HttpResponseException;
|
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;
|
||||||
import org.openmetadata.schema.api.domains.CreateDomain.DomainType;
|
import org.openmetadata.schema.api.domains.CreateDomain.DomainType;
|
||||||
import org.openmetadata.schema.entity.domains.Domain;
|
import org.openmetadata.schema.entity.domains.Domain;
|
||||||
@ -24,6 +25,13 @@ public class DomainResourceTest extends EntityResourceTest<Domain, CreateDomain>
|
|||||||
public DomainResourceTest() {
|
public DomainResourceTest() {
|
||||||
super(Entity.DOMAIN, Domain.class, DomainList.class, "domains", DomainResource.FIELDS);
|
super(Entity.DOMAIN, Domain.class, DomainList.class, "domains", DomainResource.FIELDS);
|
||||||
supportsFieldsQueryParam = false; // TODO
|
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
|
@Override
|
||||||
@ -31,6 +39,7 @@ public class DomainResourceTest extends EntityResourceTest<Domain, CreateDomain>
|
|||||||
return new CreateDomain()
|
return new CreateDomain()
|
||||||
.withName(name)
|
.withName(name)
|
||||||
.withDomainType(DomainType.AGGREGATE)
|
.withDomainType(DomainType.AGGREGATE)
|
||||||
|
.withDescription("name")
|
||||||
.withExperts(listOf(USER1.getFullyQualifiedName()));
|
.withExperts(listOf(USER1.getFullyQualifiedName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,6 @@ public class EventSubscriptionResourceTest extends EntityResourceTest<EventSubsc
|
|||||||
supportedNameCharacters = supportedNameCharacters.replace(" ", ""); // Space not supported
|
supportedNameCharacters = supportedNameCharacters.replace(" ", ""); // Space not supported
|
||||||
supportsSoftDelete = false;
|
supportsSoftDelete = false;
|
||||||
supportsFieldsQueryParam = false;
|
supportsFieldsQueryParam = false;
|
||||||
supportsEmptyDescription = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -91,12 +91,11 @@ public class GlossaryResourceTest extends EntityResourceTest<Glossary, CreateGlo
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setupGlossaries() throws IOException {
|
public void setupGlossaries() throws IOException {
|
||||||
GlossaryResourceTest glossaryResourceTest = new GlossaryResourceTest();
|
CreateGlossary createGlossary = createRequest("g1", "", "", null);
|
||||||
CreateGlossary createGlossary = glossaryResourceTest.createRequest("g1", "", "", null);
|
GLOSSARY1 = createEntity(createGlossary, ADMIN_AUTH_HEADERS);
|
||||||
GLOSSARY1 = glossaryResourceTest.createEntity(createGlossary, ADMIN_AUTH_HEADERS);
|
|
||||||
|
|
||||||
createGlossary = glossaryResourceTest.createRequest("g2", "", "", null);
|
createGlossary = createRequest("g2", "", "", null);
|
||||||
GLOSSARY2 = glossaryResourceTest.createEntity(createGlossary, ADMIN_AUTH_HEADERS);
|
GLOSSARY2 = createEntity(createGlossary, ADMIN_AUTH_HEADERS);
|
||||||
|
|
||||||
GlossaryTermResourceTest glossaryTermResourceTest = new GlossaryTermResourceTest();
|
GlossaryTermResourceTest glossaryTermResourceTest = new GlossaryTermResourceTest();
|
||||||
CreateGlossaryTerm createGlossaryTerm =
|
CreateGlossaryTerm createGlossaryTerm =
|
||||||
@ -532,11 +531,4 @@ public class GlossaryResourceTest extends EntityResourceTest<Glossary, CreateGlo
|
|||||||
assertTagPrefixAbsent(table.getColumns().get(0).getTags(), previousTermFqn);
|
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;
|
package org.openmetadata.schema;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import org.openmetadata.schema.type.EntityReference;
|
import org.openmetadata.schema.type.EntityReference;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public interface CreateEntity {
|
public interface CreateEntity {
|
||||||
String getName();
|
String getName();
|
||||||
|
|
||||||
@ -30,6 +32,14 @@ public interface CreateEntity {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default String getDomain() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
default List<String> getDataProducts() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
<K extends CreateEntity> K withName(String name);
|
<K extends CreateEntity> K withName(String name);
|
||||||
|
|
||||||
<K extends CreateEntity> K withDisplayName(String displayName);
|
<K extends CreateEntity> K withDisplayName(String displayName);
|
||||||
@ -43,4 +53,8 @@ public interface CreateEntity {
|
|||||||
default <K extends CreateEntity> K withExtension(Object extension) {
|
default <K extends CreateEntity> K withExtension(Object extension) {
|
||||||
return (K) this;
|
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;
|
import org.openmetadata.schema.utils.EntityInterfaceUtil;
|
||||||
|
|
||||||
/** Interface to be implemented by all entities to provide a way to access all the common fields. */
|
/** Interface to be implemented by all entities to provide a way to access all the common fields. */
|
||||||
|
@SuppressWarnings("unused")
|
||||||
public interface EntityInterface {
|
public interface EntityInterface {
|
||||||
// Lower case entity name to canonical entity name map
|
// Lower case entity name to canonical entity name map
|
||||||
Map<String, String> CANONICAL_ENTITY_NAME_MAP = new HashMap<>();
|
Map<String, String> CANONICAL_ENTITY_NAME_MAP = new HashMap<>();
|
||||||
@ -81,6 +82,14 @@ public interface EntityInterface {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default EntityReference getDomain() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
default List<EntityReference> getDataProducts() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
void setId(UUID id);
|
void setId(UUID id);
|
||||||
|
|
||||||
void setDescription(String description);
|
void setDescription(String description);
|
||||||
@ -115,6 +124,14 @@ public interface EntityInterface {
|
|||||||
/* no-op implementation to be overridden */
|
/* 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);
|
<T extends EntityInterface> T withHref(URI href);
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
|
@ -41,6 +41,17 @@
|
|||||||
"service": {
|
"service": {
|
||||||
"description": "Link to the chart service where this chart is hosted in",
|
"description": "Link to the chart service where this chart is hosted in",
|
||||||
"$ref": "../../type/basic.json#/definitions/fullyQualifiedEntityName"
|
"$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"],
|
"required": ["name", "service"],
|
||||||
|
@ -71,6 +71,10 @@
|
|||||||
"extension": {
|
"extension": {
|
||||||
"description": "Entity extension data with custom attributes added to the entity.",
|
"description": "Entity extension data with custom attributes added to the entity.",
|
||||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Fully qualified name of the domain the Container belongs to.",
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name", "service"],
|
"required": ["name", "service"],
|
||||||
|
@ -65,6 +65,17 @@
|
|||||||
"extension": {
|
"extension": {
|
||||||
"description": "Entity extension data with custom attributes added to the entity.",
|
"description": "Entity extension data with custom attributes added to the entity.",
|
||||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
"$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"],
|
"required": ["name", "service"],
|
||||||
|
@ -58,6 +58,10 @@
|
|||||||
"project": {
|
"project": {
|
||||||
"description": "Name of the project / workspace / collection in which the dataModel is contained",
|
"description": "Name of the project / workspace / collection in which the dataModel is contained",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Fully qualified name of the domain the Dashboard Data Model belongs to.",
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name", "service", "dataModelType", "columns"],
|
"required": ["name", "service", "dataModelType", "columns"],
|
||||||
|
@ -48,6 +48,10 @@
|
|||||||
"extension": {
|
"extension": {
|
||||||
"description": "Entity extension data with custom attributes added to the entity.",
|
"description": "Entity extension data with custom attributes added to the entity.",
|
||||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Fully qualified name of the domain the Database belongs to.",
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name", "service"],
|
"required": ["name", "service"],
|
||||||
|
@ -44,6 +44,10 @@
|
|||||||
"extension": {
|
"extension": {
|
||||||
"description": "Entity extension data with custom attributes added to the entity.",
|
"description": "Entity extension data with custom attributes added to the entity.",
|
||||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Fully qualified name of the domain the Database Schema belongs to.",
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"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.",
|
"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",
|
"type" : "boolean",
|
||||||
"default" : "false"
|
"default" : "false"
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Fully qualified name of the domain the Glossary belongs to.",
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name", "description"],
|
"required": ["name", "description"],
|
||||||
|
@ -75,6 +75,10 @@
|
|||||||
"extension": {
|
"extension": {
|
||||||
"description": "Entity extension data with custom attributes added to the entity.",
|
"description": "Entity extension data with custom attributes added to the entity.",
|
||||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Fully qualified name of the domain the MLModel belongs to.",
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name", "algorithm", "service"],
|
"required": ["name", "algorithm", "service"],
|
||||||
|
@ -68,6 +68,10 @@
|
|||||||
"description": "Scheduler Interval for the pipeline in cron format.",
|
"description": "Scheduler Interval for the pipeline in cron format.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": null
|
"default": null
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Fully qualified name of the domain the Pipeline belongs to.",
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name", "service"],
|
"required": ["name", "service"],
|
||||||
|
@ -77,6 +77,17 @@
|
|||||||
"sourceUrl": {
|
"sourceUrl": {
|
||||||
"description": "Source URL of table.",
|
"description": "Source URL of table.",
|
||||||
"$ref": "../../type/basic.json#/definitions/sourceUrl"
|
"$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"],
|
"required": ["name", "columns", "databaseSchema"],
|
||||||
|
@ -79,6 +79,18 @@
|
|||||||
"extension": {
|
"extension": {
|
||||||
"description": "Entity extension data with custom attributes added to the entity.",
|
"description": "Entity extension data with custom attributes added to the entity.",
|
||||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
"$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"],
|
"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
|
"default": null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["id", "name", "domainType","href"],
|
"required": ["id", "name", "description", "domainType","href"],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,10 @@
|
|||||||
"owner": {
|
"owner": {
|
||||||
"description": "Owner of this dashboard service.",
|
"description": "Owner of this dashboard service.",
|
||||||
"$ref": "../../type/entityReference.json"
|
"$ref": "../../type/entityReference.json"
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Fully qualified name of the domain the Dashboard Service belongs to.",
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name", "serviceType", "connection"],
|
"required": ["name", "serviceType", "connection"],
|
||||||
|
@ -37,6 +37,10 @@
|
|||||||
"owner": {
|
"owner": {
|
||||||
"description": "Owner of this database service.",
|
"description": "Owner of this database service.",
|
||||||
"$ref": "../../type/entityReference.json"
|
"$ref": "../../type/entityReference.json"
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Fully qualified name of the domain the Database Service belongs to.",
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name", "serviceType", "connection"],
|
"required": ["name", "serviceType", "connection"],
|
||||||
|
@ -37,6 +37,10 @@
|
|||||||
"owner": {
|
"owner": {
|
||||||
"description": "Owner of this messaging service.",
|
"description": "Owner of this messaging service.",
|
||||||
"$ref": "../../type/entityReference.json"
|
"$ref": "../../type/entityReference.json"
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Fully qualified name of the domain the Messaging Service belongs to.",
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name", "serviceType", "connection"],
|
"required": ["name", "serviceType", "connection"],
|
||||||
|
@ -37,6 +37,10 @@
|
|||||||
"owner": {
|
"owner": {
|
||||||
"description": "Owner of this mlModel service.",
|
"description": "Owner of this mlModel service.",
|
||||||
"$ref": "../../type/entityReference.json"
|
"$ref": "../../type/entityReference.json"
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Fully qualified name of the domain the MLModel Service belongs to.",
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name", "serviceType", "connection"],
|
"required": ["name", "serviceType", "connection"],
|
||||||
|
@ -42,6 +42,10 @@
|
|||||||
"description": "Scheduler Interval for the pipeline in cron format.",
|
"description": "Scheduler Interval for the pipeline in cron format.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": null
|
"default": null
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Fully qualified name of the domain the Pipeline Service belongs to.",
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name", "serviceType", "connection"],
|
"required": ["name", "serviceType", "connection"],
|
||||||
|
@ -37,6 +37,10 @@
|
|||||||
"owner": {
|
"owner": {
|
||||||
"description": "Owner of this object store service.",
|
"description": "Owner of this object store service.",
|
||||||
"$ref": "../../type/entityReference.json"
|
"$ref": "../../type/entityReference.json"
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Fully qualified name of the domain the Storage Service belongs to.",
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name", "serviceType", "connection"],
|
"required": ["name", "serviceType", "connection"],
|
||||||
|
@ -80,6 +80,10 @@
|
|||||||
"$ref": "../../type/basic.json#/definitions/uuid"
|
"$ref": "../../type/basic.json#/definitions/uuid"
|
||||||
},
|
},
|
||||||
"default": null
|
"default": null
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Fully qualified name of the domain the Team belongs to.",
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name", "teamType"],
|
"required": ["name", "teamType"],
|
||||||
|
@ -138,6 +138,14 @@
|
|||||||
"description": "When `true` indicates the entity has been soft deleted.",
|
"description": "When `true` indicates the entity has been soft deleted.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"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"],
|
"required": ["id", "name", "service"],
|
||||||
|
@ -167,6 +167,10 @@
|
|||||||
"extension": {
|
"extension": {
|
||||||
"description": "Entity extension data with custom attributes added to the entity.",
|
"description": "Entity extension data with custom attributes added to the entity.",
|
||||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
"$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": [
|
"required": [
|
||||||
|
@ -126,6 +126,14 @@
|
|||||||
"extension": {
|
"extension": {
|
||||||
"description": "Entity extension data with custom attributes added to the entity.",
|
"description": "Entity extension data with custom attributes added to the entity.",
|
||||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
"$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"],
|
"required": ["id", "name", "service"],
|
||||||
|
@ -137,6 +137,10 @@
|
|||||||
"project": {
|
"project": {
|
||||||
"description": "Name of the project / workspace / collection in which the dataModel is contained",
|
"description": "Name of the project / workspace / collection in which the dataModel is contained",
|
||||||
"type": "string"
|
"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": [
|
"required": [
|
||||||
|
@ -107,6 +107,10 @@
|
|||||||
"extension": {
|
"extension": {
|
||||||
"description": "Entity extension data with custom attributes added to the entity.",
|
"description": "Entity extension data with custom attributes added to the entity.",
|
||||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
"$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"],
|
"required": ["name", "service"],
|
||||||
|
@ -102,6 +102,10 @@
|
|||||||
"extension": {
|
"extension": {
|
||||||
"description": "Entity extension data with custom attributes added to the entity.",
|
"description": "Entity extension data with custom attributes added to the entity.",
|
||||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
"$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"],
|
"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.",
|
"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",
|
"type" : "boolean",
|
||||||
"default" : "false"
|
"default" : "false"
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Domain the Glossary belongs to.",
|
||||||
|
"$ref": "../../type/entityReference.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["id", "name", "description"],
|
"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.",
|
"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",
|
"type" : "boolean",
|
||||||
"default" : "false"
|
"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"],
|
"required": ["id", "name", "description", "glossary"],
|
||||||
|
@ -72,6 +72,10 @@
|
|||||||
"description": "When `true` indicates the entity has been soft deleted.",
|
"description": "When `true` indicates the entity has been soft deleted.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Domain the Metrics belongs to.",
|
||||||
|
"$ref": "../../type/entityReference.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["id", "name", "service"],
|
"required": ["id", "name", "service"],
|
||||||
|
@ -264,7 +264,12 @@
|
|||||||
"extension": {
|
"extension": {
|
||||||
"description": "Entity extension data with custom attributes added to the entity.",
|
"description": "Entity extension data with custom attributes added to the entity.",
|
||||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
"$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"],
|
"required": ["id", "name", "algorithm", "service"],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
@ -253,7 +253,12 @@
|
|||||||
"description": "Scheduler Interval for the pipeline in cron format.",
|
"description": "Scheduler Interval for the pipeline in cron format.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": null
|
"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"],
|
"required": ["id", "name", "service"],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
@ -1006,6 +1006,14 @@
|
|||||||
"sourceUrl": {
|
"sourceUrl": {
|
||||||
"description": "Source URL of table.",
|
"description": "Source URL of table.",
|
||||||
"$ref": "../../type/basic.json#/definitions/sourceUrl"
|
"$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": [
|
"required": [
|
||||||
|
@ -152,6 +152,14 @@
|
|||||||
"extension": {
|
"extension": {
|
||||||
"description": "Entity extension data with custom attributes added to the entity.",
|
"description": "Entity extension data with custom attributes added to the entity.",
|
||||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
"$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"],
|
"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"
|
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["id", "name", "domainType, ","href"],
|
"required": ["id", "name", "description", "domainType, ","href"],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
|
@ -178,6 +178,10 @@
|
|||||||
"description": "When `true` indicates the entity has been soft deleted.",
|
"description": "When `true` indicates the entity has been soft deleted.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Domain the Dashboard service belongs to.",
|
||||||
|
"$ref": "../../type/entityReference.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["id", "name", "serviceType"],
|
"required": ["id", "name", "serviceType"],
|
||||||
|
@ -332,6 +332,10 @@
|
|||||||
"description": "When `true` indicates the entity has been soft deleted.",
|
"description": "When `true` indicates the entity has been soft deleted.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Domain the Database service belongs to.",
|
||||||
|
"$ref": "../../type/entityReference.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["id", "name", "serviceType"],
|
"required": ["id", "name", "serviceType"],
|
||||||
|
@ -139,6 +139,10 @@
|
|||||||
"description": "When `true` indicates the entity has been soft deleted.",
|
"description": "When `true` indicates the entity has been soft deleted.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Domain the Messaging service belongs to.",
|
||||||
|
"$ref": "../../type/entityReference.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["id", "name", "serviceType"],
|
"required": ["id", "name", "serviceType"],
|
||||||
|
@ -131,6 +131,10 @@
|
|||||||
"description": "When `true` indicates the entity has been soft deleted.",
|
"description": "When `true` indicates the entity has been soft deleted.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Domain the MLModel service belongs to.",
|
||||||
|
"$ref": "../../type/entityReference.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["id", "name", "serviceType"],
|
"required": ["id", "name", "serviceType"],
|
||||||
|
@ -180,6 +180,10 @@
|
|||||||
"description": "When `true` indicates the entity has been soft deleted.",
|
"description": "When `true` indicates the entity has been soft deleted.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Domain the Pipeline service belongs to.",
|
||||||
|
"$ref": "../../type/entityReference.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
@ -121,6 +121,10 @@
|
|||||||
"description": "When `true` indicates the entity has been soft deleted.",
|
"description": "When `true` indicates the entity has been soft deleted.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Domain the Storage service belongs to.",
|
||||||
|
"$ref": "../../type/entityReference.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["id", "name", "serviceType"],
|
"required": ["id", "name", "serviceType"],
|
||||||
|
@ -123,6 +123,10 @@
|
|||||||
"policies": {
|
"policies": {
|
||||||
"description": "Policies that is attached to this team.",
|
"description": "Policies that is attached to this team.",
|
||||||
"$ref": "../../type/entityReferenceList.json#/definitions/entityReferenceList"
|
"$ref": "../../type/entityReferenceList.json#/definitions/entityReferenceList"
|
||||||
|
},
|
||||||
|
"domain" : {
|
||||||
|
"description": "Domain the Team belongs to.",
|
||||||
|
"$ref": "../../type/entityReference.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["id", "name", "href"],
|
"required": ["id", "name", "href"],
|
||||||
|
@ -132,6 +132,10 @@
|
|||||||
"isEmailVerified": {
|
"isEmailVerified": {
|
||||||
"description": "If the User has verified the mail",
|
"description": "If the User has verified the mail",
|
||||||
"type": "boolean"
|
"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,
|
"additionalProperties": false,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user