Fixes #6554 Add support for team of type Group (#6588)

* Fixes #6554 Add support for team of type Group

* Fixing test failure
This commit is contained in:
Suresh Srinivas 2022-08-05 10:49:42 -07:00 committed by GitHub
parent 29248437c3
commit 7825986105
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 101 additions and 79 deletions

View File

@ -1,5 +1,5 @@
UPDATE team_entity UPDATE team_entity
SET json = JSON_INSERT(json, '$.teamType', 'Department'); SET json = JSON_INSERT(json, '$.teamType', 'Group');
ALTER TABLE team_entity ALTER TABLE team_entity
ADD teamType VARCHAR(64) GENERATED ALWAYS AS (json ->> '$.teamType') NOT NULL; ADD teamType VARCHAR(64) GENERATED ALWAYS AS (json ->> '$.teamType') NOT NULL;

View File

@ -1,5 +1,5 @@
UPDATE team_entity UPDATE team_entity
SET json = JSONB_SET(json, '{teamType}', '"Department"', true); SET json = JSONB_SET(json, '{teamType}', '"Group"', true);
ALTER TABLE team_entity ALTER TABLE team_entity
ADD teamType VARCHAR(64) GENERATED ALWAYS AS (json ->> 'teamType') STORED NOT NULL; ADD teamType VARCHAR(64) GENERATED ALWAYS AS (json ->> 'teamType') STORED NOT NULL;

View File

@ -138,4 +138,12 @@ public final class CatalogExceptionMessage {
public static String createOrganization() { public static String createOrganization() {
return "Only one Organization is allowed. New Organization type can't be created"; return "Only one Organization is allowed. New Organization type can't be created";
} }
public static String createGroup() {
return "Team of type Group can't have children of type team. Only users are allowed as part of the team";
}
public static String invalidTeamOwner(TeamType teamType) {
return String.format("Team of type %s can't own entities. Only Team of type Group can own entities.", teamType);
}
} }

View File

@ -60,7 +60,6 @@ public class ChartRepository extends EntityRepository<Chart> {
chart.setService(dashboardService.getEntityReference()); chart.setService(dashboardService.getEntityReference());
chart.setServiceType(dashboardService.getServiceType()); chart.setServiceType(dashboardService.getServiceType());
setFullyQualifiedName(chart); setFullyQualifiedName(chart);
chart.setOwner(Entity.getEntityReference(chart.getOwner()));
chart.setTags(addDerivedTags(chart.getTags())); chart.setTags(addDerivedTags(chart.getTags()));
} }

View File

@ -108,7 +108,6 @@ public class DashboardRepository extends EntityRepository<Dashboard> {
public void prepare(Dashboard dashboard) throws IOException { public void prepare(Dashboard dashboard) throws IOException {
populateService(dashboard); populateService(dashboard);
setFullyQualifiedName(dashboard); setFullyQualifiedName(dashboard);
populateOwner(dashboard.getOwner()); // Validate owner
dashboard.setTags(addDerivedTags(dashboard.getTags())); dashboard.setTags(addDerivedTags(dashboard.getTags()));
dashboard.setCharts(getCharts(dashboard.getCharts())); dashboard.setCharts(getCharts(dashboard.getCharts()));
} }

View File

@ -63,7 +63,6 @@ public class DatabaseRepository extends EntityRepository<Database> {
public void prepare(Database database) throws IOException { public void prepare(Database database) throws IOException {
populateService(database); populateService(database);
setFullyQualifiedName(database); setFullyQualifiedName(database);
populateOwner(database.getOwner()); // Validate owner
} }
@Override @Override

View File

@ -56,7 +56,6 @@ public class DatabaseSchemaRepository extends EntityRepository<DatabaseSchema> {
public void prepare(DatabaseSchema schema) throws IOException { public void prepare(DatabaseSchema schema) throws IOException {
populateDatabase(schema); populateDatabase(schema);
setFullyQualifiedName(schema); setFullyQualifiedName(schema);
populateOwner(schema.getOwner()); // Validate owner
} }
@Override @Override

View File

@ -464,6 +464,7 @@ public abstract class EntityRepository<T extends EntityInterface> {
updated.setUpdatedAt(System.currentTimeMillis()); updated.setUpdatedAt(System.currentTimeMillis());
prepare(updated); prepare(updated);
populateOwner(updated.getOwner());
validateExtension(updated); validateExtension(updated);
restorePatchAttributes(original, updated); restorePatchAttributes(original, updated);

View File

@ -60,7 +60,6 @@ public class GlossaryRepository extends EntityRepository<Glossary> {
@Override @Override
public void prepare(Glossary glossary) throws IOException { public void prepare(Glossary glossary) throws IOException {
setFullyQualifiedName(glossary); setFullyQualifiedName(glossary);
glossary.setOwner(Entity.getEntityReference(glossary.getOwner()));
validateUsers(glossary.getReviewers()); validateUsers(glossary.getReviewers());
glossary.setTags(addDerivedTags(glossary.getTags())); glossary.setTags(addDerivedTags(glossary.getTags()));
} }

View File

@ -67,7 +67,6 @@ public class IngestionPipelineRepository extends EntityRepository<IngestionPipel
EntityReference entityReference = Entity.getEntityReference(ingestionPipeline.getService()); EntityReference entityReference = Entity.getEntityReference(ingestionPipeline.getService());
ingestionPipeline.setService(entityReference); ingestionPipeline.setService(entityReference);
setFullyQualifiedName(ingestionPipeline); setFullyQualifiedName(ingestionPipeline);
ingestionPipeline.setOwner(Entity.getEntityReference(ingestionPipeline.getOwner()));
} }
@Override @Override

View File

@ -166,7 +166,6 @@ public class LocationRepository extends EntityRepository<Location> {
location.setService(storageService.getEntityReference()); location.setService(storageService.getEntityReference());
location.setServiceType(storageService.getServiceType()); location.setServiceType(storageService.getServiceType());
setFullyQualifiedName(location); setFullyQualifiedName(location);
populateOwner(location.getOwner()); // Validate owner
location.setTags(addDerivedTags(location.getTags())); location.setTags(addDerivedTags(location.getTags()));
} }

View File

@ -59,7 +59,6 @@ public class MetricsRepository extends EntityRepository<Metrics> {
@Override @Override
public void prepare(Metrics metrics) throws IOException { public void prepare(Metrics metrics) throws IOException {
populateOwner(metrics.getOwner()); // Validate owner
metrics.setService(getService(metrics.getService())); metrics.setService(getService(metrics.getService()));
setFullyQualifiedName(metrics); setFullyQualifiedName(metrics);
metrics.setTags(addDerivedTags(metrics.getTags())); metrics.setTags(addDerivedTags(metrics.getTags()));

View File

@ -141,9 +141,6 @@ public class MlModelRepository extends EntityRepository<MlModel> {
setMlFeatureFQN(mlModel.getFullyQualifiedName(), mlModel.getMlFeatures()); setMlFeatureFQN(mlModel.getFullyQualifiedName(), mlModel.getMlFeatures());
} }
// Check if owner is valid and set the relationship
populateOwner(mlModel.getOwner());
// Check that the dashboard exists // Check that the dashboard exists
if (mlModel.getDashboard() != null) { if (mlModel.getDashboard() != null) {
daoCollection.dashboardDAO().findEntityReferenceById(mlModel.getDashboard().getId()); daoCollection.dashboardDAO().findEntityReferenceById(mlModel.getDashboard().getId());

View File

@ -214,7 +214,6 @@ public class PipelineRepository extends EntityRepository<Pipeline> {
public void prepare(Pipeline pipeline) throws IOException { public void prepare(Pipeline pipeline) throws IOException {
populateService(pipeline); populateService(pipeline);
setFullyQualifiedName(pipeline); setFullyQualifiedName(pipeline);
populateOwner(pipeline.getOwner()); // Validate owner
pipeline.setTags(addDerivedTags(pipeline.getTags())); pipeline.setTags(addDerivedTags(pipeline.getTags()));
} }

View File

@ -85,8 +85,6 @@ public class PolicyRepository extends EntityRepository<Policy> {
setFullyQualifiedName(policy); setFullyQualifiedName(policy);
validateRules(policy); validateRules(policy);
policy.setLocation(getLocationReference(policy)); policy.setLocation(getLocationReference(policy));
// Check if owner is valid and set the relationship
populateOwner(policy.getOwner());
} }
@Override @Override

View File

@ -46,7 +46,6 @@ public class ReportRepository extends EntityRepository<Report> {
public void prepare(Report report) throws IOException { public void prepare(Report report) throws IOException {
// TODO report does not have service yet // TODO report does not have service yet
setFullyQualifiedName(report); setFullyQualifiedName(report);
report.setOwner(Entity.getEntityReference(report.getOwner()));
} }
@Override @Override

View File

@ -4,7 +4,6 @@ import static org.openmetadata.catalog.Entity.FIELD_OWNER;
import static org.openmetadata.catalog.util.EntityUtil.objectMatch; import static org.openmetadata.catalog.util.EntityUtil.objectMatch;
import java.io.IOException; import java.io.IOException;
import org.openmetadata.catalog.Entity;
import org.openmetadata.catalog.ServiceConnectionEntityInterface; import org.openmetadata.catalog.ServiceConnectionEntityInterface;
import org.openmetadata.catalog.ServiceEntityInterface; import org.openmetadata.catalog.ServiceEntityInterface;
import org.openmetadata.catalog.entity.services.ServiceType; import org.openmetadata.catalog.entity.services.ServiceType;
@ -64,8 +63,6 @@ public abstract class ServiceRepository<T extends ServiceEntityInterface, S exte
@Override @Override
public void prepare(T service) throws IOException { public void prepare(T service) throws IOException {
setFullyQualifiedName(service); setFullyQualifiedName(service);
// Check if owner is valid and set the relationship
service.setOwner(Entity.getEntityReference(service.getOwner()));
} }
protected abstract String getServiceType(T service); protected abstract String getServiceType(T service);

View File

@ -46,8 +46,6 @@ public class StorageServiceRepository extends EntityRepository<StorageService> {
@Override @Override
public void prepare(StorageService entity) throws IOException { public void prepare(StorageService entity) throws IOException {
setFullyQualifiedName(entity); setFullyQualifiedName(entity);
// Check if owner is valid and set the relationship
entity.setOwner(Entity.getEntityReference(entity.getOwner()));
} }
@Override @Override

View File

@ -642,9 +642,6 @@ public class TableRepository extends EntityRepository<Table> {
setColumnFQN(table.getFullyQualifiedName(), table.getColumns()); setColumnFQN(table.getFullyQualifiedName(), table.getColumns());
// Check if owner is valid and set the relationship
table.setOwner(Entity.getEntityReference(table.getOwner()));
// Validate table tags and add derived tags to the list // Validate table tags and add derived tags to the list
table.setTags(addDerivedTags(table.getTags())); table.setTags(addDerivedTags(table.getTags()));

View File

@ -82,7 +82,6 @@ public class TeamRepository extends EntityRepository<Team> {
@Override @Override
public void prepare(Team team) throws IOException { public void prepare(Team team) throws IOException {
setFullyQualifiedName(team); setFullyQualifiedName(team);
populateOwner(team.getOwner()); // Validate owner
populateParents(team); // Validate parents populateParents(team); // Validate parents
populateChildren(team); // Validate children populateChildren(team); // Validate children
validateUsers(team.getUsers()); validateUsers(team.getUsers());

View File

@ -65,7 +65,6 @@ public class TestCaseRepository extends EntityRepository<TestCase> {
Entity.getEntity(test.getTestDefinition(), EntityUtil.Fields.EMPTY_FIELDS, Include.NON_DELETED); Entity.getEntity(test.getTestDefinition(), EntityUtil.Fields.EMPTY_FIELDS, Include.NON_DELETED);
validateTestParameters(test.getParameterValues(), testDefinition.getParameterDefinition()); validateTestParameters(test.getParameterValues(), testDefinition.getParameterDefinition());
test.setFullyQualifiedName(FullyQualifiedName.add(tableRef.getFullyQualifiedName(), test.getName())); test.setFullyQualifiedName(FullyQualifiedName.add(tableRef.getFullyQualifiedName(), test.getName()));
test.setOwner(Entity.getEntityReference(test.getOwner()));
} }
private EntityReference getEntity(TestCase test) throws IOException { private EntityReference getEntity(TestCase test) throws IOException {

View File

@ -3,7 +3,6 @@ package org.openmetadata.catalog.jdbi3;
import static org.openmetadata.catalog.Entity.TEST_DEFINITION; import static org.openmetadata.catalog.Entity.TEST_DEFINITION;
import java.io.IOException; import java.io.IOException;
import org.openmetadata.catalog.Entity;
import org.openmetadata.catalog.resources.dqtests.TestDefinitionResource; import org.openmetadata.catalog.resources.dqtests.TestDefinitionResource;
import org.openmetadata.catalog.tests.TestDefinition; import org.openmetadata.catalog.tests.TestDefinition;
import org.openmetadata.catalog.type.EntityReference; import org.openmetadata.catalog.type.EntityReference;
@ -33,7 +32,6 @@ public class TestDefinitionRepository extends EntityRepository<TestDefinition> {
@Override @Override
public void prepare(TestDefinition entity) throws IOException { public void prepare(TestDefinition entity) throws IOException {
setFullyQualifiedName(entity); setFullyQualifiedName(entity);
entity.setOwner(Entity.getEntityReference(entity.getOwner()));
// validate test platforms // validate test platforms
if (entity.getTestPlatforms() == null || entity.getTestPlatforms().isEmpty()) { if (entity.getTestPlatforms() == null || entity.getTestPlatforms().isEmpty()) {
throw new IllegalArgumentException("testPlatforms must not be empty"); throw new IllegalArgumentException("testPlatforms must not be empty");

View File

@ -3,7 +3,6 @@ package org.openmetadata.catalog.jdbi3;
import static org.openmetadata.catalog.Entity.TEST_SUITE; import static org.openmetadata.catalog.Entity.TEST_SUITE;
import java.io.IOException; import java.io.IOException;
import org.openmetadata.catalog.Entity;
import org.openmetadata.catalog.resources.dqtests.TestSuiteResource; import org.openmetadata.catalog.resources.dqtests.TestSuiteResource;
import org.openmetadata.catalog.tests.TestSuite; import org.openmetadata.catalog.tests.TestSuite;
import org.openmetadata.catalog.type.EntityReference; import org.openmetadata.catalog.type.EntityReference;
@ -33,7 +32,6 @@ public class TestSuiteRepository extends EntityRepository<TestSuite> {
@Override @Override
public void prepare(TestSuite entity) throws IOException { public void prepare(TestSuite entity) throws IOException {
setFullyQualifiedName(entity); setFullyQualifiedName(entity);
entity.setOwner(Entity.getEntityReference(entity.getOwner()));
} }
@Override @Override

View File

@ -64,7 +64,6 @@ public class TopicRepository extends EntityRepository<Topic> {
topic.setService(messagingService.getEntityReference()); topic.setService(messagingService.getEntityReference());
topic.setServiceType(messagingService.getServiceType()); topic.setServiceType(messagingService.getServiceType());
setFullyQualifiedName(topic); setFullyQualifiedName(topic);
topic.setOwner(Entity.getEntityReference(topic.getOwner()));
topic.setTags(addDerivedTags(topic.getTags())); topic.setTags(addDerivedTags(topic.getTags()));
} }

View File

@ -14,11 +14,15 @@ import lombok.extern.slf4j.Slf4j;
import org.openmetadata.catalog.CreateEntity; import org.openmetadata.catalog.CreateEntity;
import org.openmetadata.catalog.Entity; import org.openmetadata.catalog.Entity;
import org.openmetadata.catalog.EntityInterface; import org.openmetadata.catalog.EntityInterface;
import org.openmetadata.catalog.api.teams.CreateTeam.TeamType;
import org.openmetadata.catalog.entity.teams.Team;
import org.openmetadata.catalog.exception.CatalogExceptionMessage;
import org.openmetadata.catalog.jdbi3.EntityRepository; import org.openmetadata.catalog.jdbi3.EntityRepository;
import org.openmetadata.catalog.jdbi3.ListFilter; import org.openmetadata.catalog.jdbi3.ListFilter;
import org.openmetadata.catalog.security.Authorizer; import org.openmetadata.catalog.security.Authorizer;
import org.openmetadata.catalog.security.policyevaluator.OperationContext; import org.openmetadata.catalog.security.policyevaluator.OperationContext;
import org.openmetadata.catalog.security.policyevaluator.ResourceContext; import org.openmetadata.catalog.security.policyevaluator.ResourceContext;
import org.openmetadata.catalog.type.EntityReference;
import org.openmetadata.catalog.type.Include; import org.openmetadata.catalog.type.Include;
import org.openmetadata.catalog.type.MetadataOperation; import org.openmetadata.catalog.type.MetadataOperation;
import org.openmetadata.catalog.util.EntityUtil.Fields; import org.openmetadata.catalog.util.EntityUtil.Fields;
@ -164,18 +168,33 @@ public abstract class EntityResource<T extends EntityInterface, K extends Entity
return response.toResponse(); return response.toResponse();
} }
public T copy(T entity, CreateEntity request, String updatedBy) { public T copy(T entity, CreateEntity request, String updatedBy) throws IOException {
EntityReference owner = validateOwner(request.getOwner());
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(request.getOwner()); entity.setOwner(owner);
entity.setExtension(request.getExtension()); entity.setExtension(request.getExtension());
entity.setUpdatedBy(updatedBy); entity.setUpdatedBy(updatedBy);
entity.setUpdatedAt(System.currentTimeMillis()); entity.setUpdatedAt(System.currentTimeMillis());
return entity; return entity;
} }
private EntityReference validateOwner(EntityReference owner) throws IOException {
if (owner == null) {
return null;
}
if (owner.getType().equals(Entity.TEAM)) {
Team team = Entity.getEntity(Entity.TEAM, owner.getId(), Fields.EMPTY_FIELDS, Include.ALL);
if (!team.getTeamType().equals(TeamType.GROUP)) {
throw new IllegalArgumentException(CatalogExceptionMessage.invalidTeamOwner(team.getTeamType()));
}
return team.getEntityReference();
}
return Entity.getEntityReferenceById(owner.getType(), owner.getId(), Include.ALL);
}
protected ResourceContext getResourceContext() { protected ResourceContext getResourceContext() {
return ResourceContext.builder().resource(entityType).entityRepository(dao).build(); return ResourceContext.builder().resource(entityType).entityRepository(dao).build();
} }

View File

@ -307,7 +307,7 @@ public class BotResource extends EntityResource<Bot, BotRepository> {
return delete(uriInfo, securityContext, id, true, hardDelete, false); return delete(uriInfo, securityContext, id, true, hardDelete, false);
} }
private Bot getBot(CreateBot create, String user) { private Bot getBot(CreateBot create, String user) throws IOException {
return copy(new Bot(), create, user).withBotUser(create.getBotUser()); return copy(new Bot(), create, user).withBotUser(create.getBotUser());
} }
} }

View File

@ -387,7 +387,7 @@ public class ChartResource extends EntityResource<Chart, ChartRepository> {
return delete(uriInfo, securityContext, id, false, hardDelete, true); return delete(uriInfo, securityContext, id, false, hardDelete, true);
} }
private Chart getChart(CreateChart create, String user) { private Chart getChart(CreateChart create, String user) throws IOException {
return copy(new Chart(), create, user) return copy(new Chart(), create, user)
.withService(create.getService()) .withService(create.getService())
.withChartType(create.getChartType()) .withChartType(create.getChartType())

View File

@ -391,7 +391,7 @@ public class DashboardResource extends EntityResource<Dashboard, DashboardReposi
return delete(uriInfo, securityContext, id, false, hardDelete, true); return delete(uriInfo, securityContext, id, false, hardDelete, true);
} }
private Dashboard getDashboard(CreateDashboard create, String user) { private Dashboard getDashboard(CreateDashboard create, String user) throws IOException {
return copy(new Dashboard(), create, user) return copy(new Dashboard(), create, user)
.withService(create.getService()) .withService(create.getService())
.withCharts(create.getCharts()) .withCharts(create.getCharts())

View File

@ -366,7 +366,7 @@ public class DatabaseResource extends EntityResource<Database, DatabaseRepositor
return delete(uriInfo, securityContext, id, recursive, hardDelete, true); return delete(uriInfo, securityContext, id, recursive, hardDelete, true);
} }
private Database getDatabase(CreateDatabase create, String user) { private Database getDatabase(CreateDatabase create, String user) throws IOException {
return copy(new Database(), create, user).withService(create.getService()); return copy(new Database(), create, user).withService(create.getService());
} }
} }

View File

@ -353,7 +353,7 @@ public class DatabaseSchemaResource extends EntityResource<DatabaseSchema, Datab
return delete(uriInfo, securityContext, id, recursive, hardDelete, true); return delete(uriInfo, securityContext, id, recursive, hardDelete, true);
} }
private DatabaseSchema getDatabaseSchema(CreateDatabaseSchema create, String user) { private DatabaseSchema getDatabaseSchema(CreateDatabaseSchema create, String user) throws IOException {
return copy(new DatabaseSchema(), create, user).withDatabase(create.getDatabase()); return copy(new DatabaseSchema(), create, user).withDatabase(create.getDatabase());
} }
} }

View File

@ -944,7 +944,7 @@ public class TableResource extends EntityResource<Table, TableRepository> {
return table; return table;
} }
private Table getTable(CreateTable create, String user) { private Table getTable(CreateTable create, String user) throws IOException {
return validateNewTable( return validateNewTable(
copy(new Table(), create, user) copy(new Table(), create, user)
.withColumns(create.getColumns()) .withColumns(create.getColumns())

View File

@ -473,7 +473,7 @@ public class TestCaseResource extends EntityResource<TestCase, TestCaseRepositor
return addHref(uriInfo, testCase); return addHref(uriInfo, testCase);
} }
private TestCase getTestCase(CreateTestCase create, String user) { private TestCase getTestCase(CreateTestCase create, String user) throws IOException {
return copy(new TestCase(), create, user) return copy(new TestCase(), create, user)
.withDescription(create.getDescription()) .withDescription(create.getDescription())
.withName(create.getName()) .withName(create.getName())

View File

@ -376,7 +376,7 @@ public class TestDefinitionResource extends EntityResource<TestDefinition, TestD
return delete(uriInfo, securityContext, id, false, hardDelete, true); return delete(uriInfo, securityContext, id, false, hardDelete, true);
} }
private TestDefinition getTestDefinition(CreateTestDefinition create, String user) { private TestDefinition getTestDefinition(CreateTestDefinition create, String user) throws IOException {
return copy(new TestDefinition(), create, user) return copy(new TestDefinition(), create, user)
.withDescription(create.getDescription()) .withDescription(create.getDescription())
.withEntityType(create.getEntityType()) .withEntityType(create.getEntityType())

View File

@ -333,7 +333,7 @@ public class TestSuiteResource extends EntityResource<TestSuite, TestSuiteReposi
return delete(uriInfo, securityContext, id, false, hardDelete, true); return delete(uriInfo, securityContext, id, false, hardDelete, true);
} }
private TestSuite getTestSuite(CreateTestSuite create, String user) { private TestSuite getTestSuite(CreateTestSuite create, String user) throws IOException {
return copy(new TestSuite(), create, user) return copy(new TestSuite(), create, user)
.withDescription(create.getDescription()) .withDescription(create.getDescription())
.withScheduleInterval(create.getScheduleInterval()) .withScheduleInterval(create.getScheduleInterval())

View File

@ -345,7 +345,7 @@ public class WebhookResource extends EntityResource<Webhook, WebhookRepository>
return response; return response;
} }
public Webhook getWebhook(CreateWebhook create, String user) { public Webhook getWebhook(CreateWebhook create, String user) throws IOException {
// Add filter for soft delete events if delete event type is requested // Add filter for soft delete events if delete event type is requested
EntityUtil.addSoftDeleteFilter(create.getEventFilters()); EntityUtil.addSoftDeleteFilter(create.getEventFilters());
return copy(new Webhook(), create, user) return copy(new Webhook(), create, user)

View File

@ -349,7 +349,7 @@ public class GlossaryResource extends EntityResource<Glossary, GlossaryRepositor
return delete(uriInfo, securityContext, id, recursive, hardDelete, true); return delete(uriInfo, securityContext, id, recursive, hardDelete, true);
} }
private Glossary getGlossary(CreateGlossary create, String user) { private Glossary getGlossary(CreateGlossary create, String user) throws IOException {
return copy(new Glossary(), create, user).withReviewers(create.getReviewers()).withTags(create.getTags()); return copy(new Glossary(), create, user).withReviewers(create.getReviewers()).withTags(create.getTags());
} }
} }

View File

@ -398,7 +398,7 @@ public class GlossaryTermResource extends EntityResource<GlossaryTerm, GlossaryT
return delete(uriInfo, securityContext, id, recursive, hardDelete, true); return delete(uriInfo, securityContext, id, recursive, hardDelete, true);
} }
private GlossaryTerm getGlossaryTerm(CreateGlossaryTerm create, String user) { private GlossaryTerm getGlossaryTerm(CreateGlossaryTerm create, String user) throws IOException {
return copy(new GlossaryTerm(), create, user) return copy(new GlossaryTerm(), create, user)
.withSynonyms(create.getSynonyms()) .withSynonyms(create.getSynonyms())
.withGlossary(create.getGlossary()) .withGlossary(create.getGlossary())

View File

@ -490,7 +490,7 @@ public class LocationResource extends EntityResource<Location, LocationRepositor
return location; return location;
} }
private Location getLocation(CreateLocation create, String user) { private Location getLocation(CreateLocation create, String user) throws IOException {
return copy(new Location(), create, user) return copy(new Location(), create, user)
.withPath(create.getPath()) .withPath(create.getPath())
.withService(create.getService()) .withService(create.getService())

View File

@ -403,7 +403,7 @@ public class MlModelResource extends EntityResource<MlModel, MlModelRepository>
return delete(uriInfo, securityContext, id, false, hardDelete, true); return delete(uriInfo, securityContext, id, false, hardDelete, true);
} }
private MlModel getMlModel(CreateMlModel create, String user) { private MlModel getMlModel(CreateMlModel create, String user) throws IOException {
return copy(new MlModel(), create, user) return copy(new MlModel(), create, user)
.withService(create.getService()) .withService(create.getService())
.withDashboard(create.getDashboard()) .withDashboard(create.getDashboard())

View File

@ -528,7 +528,7 @@ public class PipelineResource extends EntityResource<Pipeline, PipelineRepositor
return delete(uriInfo, securityContext, id, false, hardDelete, true); return delete(uriInfo, securityContext, id, false, hardDelete, true);
} }
private Pipeline getPipeline(CreatePipeline create, String user) { private Pipeline getPipeline(CreatePipeline create, String user) throws IOException {
return copy(new Pipeline(), create, user) return copy(new Pipeline(), create, user)
.withService(create.getService()) .withService(create.getService())
.withTasks(create.getTasks()) .withTasks(create.getTasks())

View File

@ -395,7 +395,7 @@ public class PolicyResource extends EntityResource<Policy, PolicyRepository> {
return response; return response;
} }
private Policy getPolicy(CreatePolicy create, String user) { private Policy getPolicy(CreatePolicy create, String user) throws IOException {
Policy policy = Policy policy =
copy(new Policy(), create, user) copy(new Policy(), create, user)
.withPolicyType(create.getPolicyType()) .withPolicyType(create.getPolicyType())

View File

@ -352,7 +352,7 @@ public class DashboardServiceResource
return delete(uriInfo, securityContext, id, recursive, hardDelete, true); return delete(uriInfo, securityContext, id, recursive, hardDelete, true);
} }
private DashboardService getService(CreateDashboardService create, String user) { private DashboardService getService(CreateDashboardService create, String user) throws IOException {
return copy(new DashboardService(), create, user) return copy(new DashboardService(), create, user)
.withServiceType(create.getServiceType()) .withServiceType(create.getServiceType())
.withConnection(create.getConnection()); .withConnection(create.getConnection());

View File

@ -358,7 +358,7 @@ public class DatabaseServiceResource
return delete(uriInfo, securityContext, id, recursive, hardDelete, true); return delete(uriInfo, securityContext, id, recursive, hardDelete, true);
} }
private DatabaseService getService(CreateDatabaseService create, String user) { private DatabaseService getService(CreateDatabaseService create, String user) throws IOException {
return copy(new DatabaseService(), create, user) return copy(new DatabaseService(), create, user)
.withServiceType(create.getServiceType()) .withServiceType(create.getServiceType())
.withConnection(create.getConnection()); .withConnection(create.getConnection());

View File

@ -548,7 +548,7 @@ public class IngestionPipelineResource extends EntityResource<IngestionPipeline,
return Response.ok(lastIngestionLogs, MediaType.APPLICATION_JSON_TYPE).build(); return Response.ok(lastIngestionLogs, MediaType.APPLICATION_JSON_TYPE).build();
} }
private IngestionPipeline getIngestionPipeline(CreateIngestionPipeline create, String user) { private IngestionPipeline getIngestionPipeline(CreateIngestionPipeline create, String user) throws IOException {
OpenMetadataServerConnection openMetadataServerConnection = OpenMetadataServerConnection openMetadataServerConnection =
secretsManager.decryptServerConnection(airflowConfiguration); secretsManager.decryptServerConnection(airflowConfiguration);
openMetadataServerConnection.setSecretsManagerProvider(this.secretsManager.getSecretsManagerProvider()); openMetadataServerConnection.setSecretsManagerProvider(this.secretsManager.getSecretsManagerProvider());

View File

@ -358,7 +358,7 @@ public class MessagingServiceResource
return delete(uriInfo, securityContext, id, recursive, hardDelete, true); return delete(uriInfo, securityContext, id, recursive, hardDelete, true);
} }
private MessagingService getService(CreateMessagingService create, String user) { private MessagingService getService(CreateMessagingService create, String user) throws IOException {
return copy(new MessagingService(), create, user) return copy(new MessagingService(), create, user)
.withConnection(create.getConnection()) .withConnection(create.getConnection())
.withServiceType(create.getServiceType()); .withServiceType(create.getServiceType());

View File

@ -354,7 +354,7 @@ public class MlModelServiceResource
return delete(uriInfo, securityContext, id, recursive, hardDelete, true); return delete(uriInfo, securityContext, id, recursive, hardDelete, true);
} }
private MlModelService getService(CreateMlModelService create, String user) { private MlModelService getService(CreateMlModelService create, String user) throws IOException {
return copy(new MlModelService(), create, user) return copy(new MlModelService(), create, user)
.withServiceType(create.getServiceType()) .withServiceType(create.getServiceType())
.withConnection(create.getConnection()); .withConnection(create.getConnection());

View File

@ -353,7 +353,7 @@ public class PipelineServiceResource
return delete(uriInfo, securityContext, id, recursive, hardDelete, true); return delete(uriInfo, securityContext, id, recursive, hardDelete, true);
} }
private PipelineService getService(CreatePipelineService create, String user) { private PipelineService getService(CreatePipelineService create, String user) throws IOException {
return copy(new PipelineService(), create, user) return copy(new PipelineService(), create, user)
.withServiceType(create.getServiceType()) .withServiceType(create.getServiceType())
.withConnection(create.getConnection()); .withConnection(create.getConnection());

View File

@ -320,7 +320,7 @@ public class StorageServiceResource extends EntityResource<StorageService, Stora
return delete(uriInfo, securityContext, id, recursive, hardDelete, true); return delete(uriInfo, securityContext, id, recursive, hardDelete, true);
} }
private StorageService getService(CreateStorageService create, String user) { private StorageService getService(CreateStorageService create, String user) throws IOException {
return copy(new StorageService(), create, user).withServiceType(create.getServiceType()); return copy(new StorageService(), create, user).withServiceType(create.getServiceType());
} }
} }

View File

@ -401,7 +401,7 @@ public class RoleResource extends EntityResource<Role, RoleRepository> {
return response; return response;
} }
private Role getRole(CreateRole create, String user) { private Role getRole(CreateRole create, String user) throws IOException {
if (nullOrEmpty(create.getPolicies())) { if (nullOrEmpty(create.getPolicies())) {
throw new IllegalArgumentException("At least one policy is required to create a role"); throw new IllegalArgumentException("At least one policy is required to create a role");
} }

View File

@ -359,10 +359,13 @@ public class TeamResource extends EntityResource<Team, TeamRepository> {
return delete(uriInfo, securityContext, id, false, hardDelete, true); return delete(uriInfo, securityContext, id, false, hardDelete, true);
} }
private Team getTeam(CreateTeam ct, String user) { private Team getTeam(CreateTeam ct, String user) throws IOException {
if (ct.getTeamType().equals(TeamType.ORGANIZATION)) { if (ct.getTeamType().equals(TeamType.ORGANIZATION)) {
throw new IllegalArgumentException(CatalogExceptionMessage.createOrganization()); throw new IllegalArgumentException(CatalogExceptionMessage.createOrganization());
} }
if (ct.getTeamType().equals(TeamType.GROUP) && ct.getChildren() != null) {
throw new IllegalArgumentException(CatalogExceptionMessage.createGroup());
}
return copy(new Team(), ct, user) return copy(new Team(), ct, user)
.withProfile(ct.getProfile()) .withProfile(ct.getProfile())
.withIsJoinable(ct.getIsJoinable()) .withIsJoinable(ct.getIsJoinable())

View File

@ -422,7 +422,7 @@ public class TopicResource extends EntityResource<Topic, TopicRepository> {
return delete(uriInfo, securityContext, id, false, hardDelete, true); return delete(uriInfo, securityContext, id, false, hardDelete, true);
} }
private Topic getTopic(CreateTopic create, String user) { private Topic getTopic(CreateTopic create, String user) throws IOException {
return copy(new Topic(), create, user) return copy(new Topic(), create, user)
.withService(create.getService()) .withService(create.getService())
.withPartitions(create.getPartitions()) .withPartitions(create.getPartitions())

View File

@ -394,7 +394,7 @@ public class TypeResource extends EntityResource<Type, TypeRepository> {
return response.toResponse(); return response.toResponse();
} }
private Type getType(CreateType create, String user) { private Type getType(CreateType create, String user) throws IOException {
return copy(new Type(), create, user) return copy(new Type(), create, user)
.withFullyQualifiedName(create.getName()) .withFullyQualifiedName(create.getName())
.withCategory(create.getCategory()) .withCategory(create.getCategory())

View File

@ -8,15 +8,16 @@
"javaInterfaces": ["org.openmetadata.catalog.EntityInterface"], "javaInterfaces": ["org.openmetadata.catalog.EntityInterface"],
"definitions": { "definitions": {
"teamType" : { "teamType" : {
"description" : "Organization is the highest level entity. An Organization has one of more Business Units, Division, or Departments. A Business Unit has one or more Divisions, or Departments. A Division has one or more Divisions or Departments. A Department has one or more Departments or users.", "description" : "Organization is the highest level entity. An Organization has one of more Business Units, Division, Departments, Group, or Users. A Business Unit has one or more Divisions, Departments, Group, or Users. A Division has one or more Divisions, Departments, Group, or Users. A Department has one or more Departments, Group, or Users. A Group has a only Users",
"type" : "string", "type" : "string",
"enum": [ "enum": [
"Group",
"Department", "Department",
"Division", "Division",
"BusinessUnit", "BusinessUnit",
"Organization" "Organization"
], ],
"default": "Department" "default": "Group"
} }
}, },
"properties": { "properties": {

View File

@ -94,6 +94,7 @@ import org.openmetadata.catalog.Entity;
import org.openmetadata.catalog.EntityInterface; import org.openmetadata.catalog.EntityInterface;
import org.openmetadata.catalog.api.data.TermReference; import org.openmetadata.catalog.api.data.TermReference;
import org.openmetadata.catalog.api.teams.CreateTeam; import org.openmetadata.catalog.api.teams.CreateTeam;
import org.openmetadata.catalog.api.teams.CreateTeam.TeamType;
import org.openmetadata.catalog.entity.Type; import org.openmetadata.catalog.entity.Type;
import org.openmetadata.catalog.entity.data.Database; import org.openmetadata.catalog.entity.data.Database;
import org.openmetadata.catalog.entity.data.DatabaseSchema; import org.openmetadata.catalog.entity.data.DatabaseSchema;
@ -706,13 +707,25 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
} }
@Test @Test
void post_entityWithInvalidOwnerType_4xx(TestInfo test) { void post_entityWithInvalidOwnerType_4xx(TestInfo test) throws HttpResponseException {
if (!supportsOwner) { if (!supportsOwner) {
return; return;
} }
EntityReference owner = new EntityReference().withId(TEAM1.getId()); /* No owner type is set */ EntityReference owner = new EntityReference().withId(TEAM1.getId()); /* No owner type is set */
K create = createRequest(getEntityName(test), "", "", owner); K create = createRequest(getEntityName(test), "", "", owner);
assertResponseContains(() -> createEntity(create, ADMIN_AUTH_HEADERS), BAD_REQUEST, "type must not be null"); assertResponseContains(() -> createEntity(create, ADMIN_AUTH_HEADERS), BAD_REQUEST, "type must not be null");
// Only Team of type Group is allowed to own entities
List<Team> teams =
new TeamResourceTest().getTeamOfTypes(test, TeamType.BUSINESS_UNIT, TeamType.DEPARTMENT, TeamType.DEPARTMENT);
teams.add(ORG_TEAM);
for (Team team : teams) {
K create1 = createRequest(getEntityName(test), "", "", team.getEntityReference());
assertResponseContains(
() -> createEntity(create1, ADMIN_AUTH_HEADERS),
BAD_REQUEST,
CatalogExceptionMessage.invalidTeamOwner(team.getTeamType()));
}
} }
@Test @Test

View File

@ -24,6 +24,7 @@ import static org.openmetadata.catalog.Entity.ORGANIZATION_NAME;
import static org.openmetadata.catalog.api.teams.CreateTeam.TeamType.BUSINESS_UNIT; import static org.openmetadata.catalog.api.teams.CreateTeam.TeamType.BUSINESS_UNIT;
import static org.openmetadata.catalog.api.teams.CreateTeam.TeamType.DEPARTMENT; import static org.openmetadata.catalog.api.teams.CreateTeam.TeamType.DEPARTMENT;
import static org.openmetadata.catalog.api.teams.CreateTeam.TeamType.DIVISION; import static org.openmetadata.catalog.api.teams.CreateTeam.TeamType.DIVISION;
import static org.openmetadata.catalog.api.teams.CreateTeam.TeamType.GROUP;
import static org.openmetadata.catalog.api.teams.CreateTeam.TeamType.ORGANIZATION; import static org.openmetadata.catalog.api.teams.CreateTeam.TeamType.ORGANIZATION;
import static org.openmetadata.catalog.exception.CatalogExceptionMessage.invalidParent; import static org.openmetadata.catalog.exception.CatalogExceptionMessage.invalidParent;
import static org.openmetadata.catalog.exception.CatalogExceptionMessage.invalidParentCount; import static org.openmetadata.catalog.exception.CatalogExceptionMessage.invalidParentCount;
@ -381,19 +382,24 @@ public class TeamResourceTest extends EntityResourceTest<Team, CreateTeam> {
// Creating a parent with invalid children type is not allowed // Creating a parent with invalid children type is not allowed
// Department can't have Business unit as a child // Department can't have Business unit as a child
assertResponse( assertResponse(
() -> createWithChildren("invalidTeam", DEPARTMENT, bu11.getEntityReference()), () -> createWithChildren("invalidDepartment", DEPARTMENT, bu11.getEntityReference()),
BAD_REQUEST, BAD_REQUEST,
CatalogExceptionMessage.invalidChild("invalidTeam", DEPARTMENT, bu11)); CatalogExceptionMessage.invalidChild("invalidDepartment", DEPARTMENT, bu11));
// Department can't have Division as a child // Department can't have Division as a child
assertResponse( assertResponse(
() -> createWithChildren("invalidTeam", DEPARTMENT, div12.getEntityReference()), () -> createWithChildren("invalidDepartment", DEPARTMENT, div12.getEntityReference()),
BAD_REQUEST, BAD_REQUEST,
CatalogExceptionMessage.invalidChild("invalidTeam", DEPARTMENT, div12)); CatalogExceptionMessage.invalidChild("invalidDepartment", DEPARTMENT, div12));
// Division can't have BU as a child // Division can't have BU as a child
assertResponse( assertResponse(
() -> createWithChildren("invalidTeam", DIVISION, bu11.getEntityReference()), () -> createWithChildren("invalidDivision", DIVISION, bu11.getEntityReference()),
BAD_REQUEST, BAD_REQUEST,
CatalogExceptionMessage.invalidChild("invalidTeam", DIVISION, bu11)); CatalogExceptionMessage.invalidChild("invalidDivision", DIVISION, bu11));
// Group can't have other teams as children. Only users are allowed under the team
assertResponse(
() -> createWithChildren("invalidGroup", GROUP, bu11.getEntityReference()),
BAD_REQUEST,
CatalogExceptionMessage.createGroup());
} }
@Test @Test
@ -760,4 +766,13 @@ public class TeamResourceTest extends EntityResourceTest<Team, CreateTeam> {
.withRoles(List.of(teamManager.getId())), .withRoles(List.of(teamManager.getId())),
ADMIN_AUTH_HEADERS); ADMIN_AUTH_HEADERS);
} }
public List<Team> getTeamOfTypes(TestInfo test, TeamType... teamTypes) throws HttpResponseException {
List<Team> teams = new ArrayList<>();
int i = 0;
for (TeamType type : teamTypes) {
teams.add(createEntity(createRequest(getEntityName(test, i++)).withTeamType(type), ADMIN_AUTH_HEADERS));
}
return teams;
}
} }

View File

@ -7,5 +7,5 @@ Provides metadata version information.
from incremental import Version from incremental import Version
__version__ = Version("metadata", 0, 12, 0, dev=7) __version__ = Version("metadata", 0, 12, 0, dev=8)
__all__ = ["__version__"] __all__ = ["__version__"]

View File

@ -954,14 +954,6 @@ public abstract class EntityRepository<T extends EntityInterface> {
return getOwner(entity); return getOwner(entity);
} }
public void populateOwner(EntityReference owner) throws IOException {
if (owner == null) {
return;
}
EntityReference ref = Entity.getEntityReferenceById(owner.getType(), owner.getId(), ALL);
EntityUtil.copy(ref, owner);
}
protected void storeOwner(T entity, EntityReference owner) { protected void storeOwner(T entity, EntityReference owner) {
if (supportsOwner) { if (supportsOwner) {
// Add relationship owner --- owns ---> ownedEntity // Add relationship owner --- owns ---> ownedEntity