Fixes #6365 Support for adding policies at the team level (#6366)

This commit is contained in:
Suresh Srinivas 2022-07-26 17:33:13 -07:00 committed by GitHub
parent 7590418d9c
commit 8af3af9d32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 358 additions and 217 deletions

View File

@ -972,13 +972,23 @@ public abstract class EntityRepository<T extends EntityInterface> {
}
}
public void validateRoles(List<EntityReference> entityReferences) throws IOException {
if (entityReferences != null) {
for (EntityReference entityReference : entityReferences) {
public void validateRoles(List<EntityReference> roles) throws IOException {
if (roles != null) {
for (EntityReference entityReference : roles) {
EntityReference ref = daoCollection.roleDAO().findEntityReferenceById(entityReference.getId());
EntityUtil.copy(ref, entityReference);
}
entityReferences.sort(EntityUtil.compareEntityReference);
roles.sort(EntityUtil.compareEntityReference);
}
}
void validatePolicies(List<EntityReference> policies) throws IOException {
if (policies != null) {
for (EntityReference entityReference : policies) {
EntityReference ref = daoCollection.policyDAO().findEntityReferenceById(entityReference.getId());
EntityUtil.copy(ref, entityReference);
}
policies.sort(EntityUtil.compareEntityReference);
}
}

View File

@ -14,6 +14,7 @@
package org.openmetadata.catalog.jdbi3;
import static org.openmetadata.catalog.Entity.FIELD_OWNER;
import static org.openmetadata.catalog.Entity.POLICY;
import static org.openmetadata.catalog.Entity.TEAM;
import static org.openmetadata.catalog.api.teams.CreateTeam.TeamType.BUSINESS_UNIT;
import static org.openmetadata.catalog.api.teams.CreateTeam.TeamType.DEPARTMENT;
@ -46,8 +47,8 @@ import org.openmetadata.catalog.util.JsonUtils;
@Slf4j
public class TeamRepository extends EntityRepository<Team> {
static final String TEAM_UPDATE_FIELDS = "owner,profile,users,defaultRoles,parents,children";
static final String TEAM_PATCH_FIELDS = "owner,profile,users,defaultRoles,parents,children";
static final String TEAM_UPDATE_FIELDS = "owner,profile,users,defaultRoles,parents,children,policies";
static final String TEAM_PATCH_FIELDS = "owner,profile,users,defaultRoles,parents,children,policies";
Team organization = null;
public TeamRepository(CollectionDAO dao) {
@ -65,6 +66,7 @@ public class TeamRepository extends EntityRepository<Team> {
team.setOwner(fields.contains(FIELD_OWNER) ? getOwner(team) : null);
team.setParents(fields.contains("parents") ? getParents(team) : null);
team.setChildren(fields.contains("children") ? getChildren(team) : null);
team.setPolicies(fields.contains("policies") ? getPolicies(team) : null);
return team;
}
@ -82,6 +84,7 @@ public class TeamRepository extends EntityRepository<Team> {
populateChildren(team); // Validate children
validateUsers(team.getUsers());
validateRoles(team.getDefaultRoles());
validatePolicies(team.getPolicies());
}
@Override
@ -92,6 +95,7 @@ public class TeamRepository extends EntityRepository<Team> {
List<EntityReference> defaultRoles = team.getDefaultRoles();
List<EntityReference> parents = team.getParents();
List<EntityReference> children = team.getChildren();
List<EntityReference> policies = team.getPolicies();
// Don't store users, defaultRoles, href as JSON. Build it on the fly based on relationships
team.withUsers(null).withDefaultRoles(null).withHref(null).withOwner(null);
@ -99,7 +103,12 @@ public class TeamRepository extends EntityRepository<Team> {
store(team.getId(), team, update);
// Restore the relationships
team.withUsers(users).withDefaultRoles(defaultRoles).withOwner(owner).withParents(parents).withChildren(children);
team.withUsers(users)
.withDefaultRoles(defaultRoles)
.withOwner(owner)
.withParents(parents)
.withChildren(children)
.withPolicies(policies);
}
@Override
@ -118,6 +127,9 @@ public class TeamRepository extends EntityRepository<Team> {
for (EntityReference child : listOrEmpty(team.getChildren())) {
addRelationship(team.getId(), child.getId(), TEAM, TEAM, Relationship.PARENT_OF);
}
for (EntityReference policy : listOrEmpty(team.getPolicies())) {
addRelationship(team.getId(), policy.getId(), TEAM, POLICY, Relationship.HAS);
}
}
@Override
@ -166,6 +178,11 @@ public class TeamRepository extends EntityRepository<Team> {
return EntityUtil.populateEntityReferences(children, TEAM);
}
private List<EntityReference> getPolicies(Team team) throws IOException {
List<EntityRelationshipRecord> policies = findTo(team.getId(), TEAM, Relationship.HAS, POLICY);
return EntityUtil.populateEntityReferences(policies, POLICY);
}
private void populateChildren(Team team) throws IOException {
List<EntityReference> childrenRefs = team.getChildren();
if (childrenRefs == null) {
@ -188,7 +205,7 @@ public class TeamRepository extends EntityRepository<Team> {
}
private void populateParents(Team team) throws IOException {
// All the teams created without parents has the top Organization as the default parent
// Teams created without parents has the top Organization as the default parent
List<EntityReference> parentRefs = team.getParents();
if (parentRefs == null) {
team.setParents(new ArrayList<>());
@ -217,7 +234,8 @@ public class TeamRepository extends EntityRepository<Team> {
// Populate team refs from team entity list
private void populateTeamRefs(List<EntityReference> teamRefs, List<Team> teams) {
for (int i = 0; i < teams.size(); i++) {
EntityUtil.copy(teamRefs.get(i), teams.get(i).getEntityReference());
System.out.print("XXX copying " + teams.get(i).getEntityReference());
EntityUtil.copy(teams.get(i).getEntityReference(), teamRefs.get(i));
}
}
@ -295,6 +313,7 @@ public class TeamRepository extends EntityRepository<Team> {
updateDefaultRoles(original, updated);
updateParents(original, updated);
updateChildren(original, updated);
updatePolicies(original, updated);
}
private void updateUsers(Team origTeam, Team updatedTeam) throws JsonProcessingException {
@ -329,7 +348,14 @@ public class TeamRepository extends EntityRepository<Team> {
List<EntityReference> origParents = listOrEmpty(original.getChildren());
List<EntityReference> updatedParents = listOrEmpty(updated.getChildren());
updateToRelationships(
"parents", TEAM, original.getId(), Relationship.PARENT_OF, TEAM, origParents, updatedParents, false);
"children", TEAM, original.getId(), Relationship.PARENT_OF, TEAM, origParents, updatedParents, false);
}
private void updatePolicies(Team original, Team updated) throws JsonProcessingException {
List<EntityReference> origPolicies = listOrEmpty(original.getPolicies());
List<EntityReference> updatedPolicies = listOrEmpty(updated.getPolicies());
updateToRelationships(
"policies", TEAM, original.getId(), Relationship.HAS, POLICY, origPolicies, updatedPolicies, false);
}
}
}

View File

@ -75,6 +75,9 @@ public class TeamResource extends EntityResource<Team, TeamRepository> {
Entity.withHref(uriInfo, team.getUsers());
Entity.withHref(uriInfo, team.getDefaultRoles());
Entity.withHref(uriInfo, team.getOwns());
Entity.withHref(uriInfo, team.getParents());
Entity.withHref(uriInfo, team.getChildren());
Entity.withHref(uriInfo, team.getPolicies());
return team;
}
@ -96,7 +99,7 @@ public class TeamResource extends EntityResource<Team, TeamRepository> {
}
}
static final String FIELDS = "owner,profile,users,owns,defaultRoles,parents,children";
static final String FIELDS = "owner,profile,users,owns,defaultRoles,parents,children,policies";
@GET
@Valid
@ -358,6 +361,7 @@ public class TeamResource extends EntityResource<Team, TeamRepository> {
.withDefaultRoles(EntityUtil.toEntityReferences(ct.getDefaultRoles(), Entity.ROLE))
.withTeamType(ct.getTeamType())
.withParents(EntityUtil.toEntityReferences(ct.getParents(), Entity.TEAM))
.withChildren(EntityUtil.toEntityReferences(ct.getChildren(), Entity.TEAM));
.withChildren(EntityUtil.toEntityReferences(ct.getChildren(), Entity.TEAM))
.withPolicies(EntityUtil.toEntityReferences(ct.getPolicies(), Entity.POLICY));
}
}

View File

@ -68,6 +68,14 @@
"description": "Can any user join this team during sign up? Value of true indicates yes, and false no.",
"type": "boolean",
"default": true
},
"policies": {
"description": "Policies that is attached to this team.",
"type": "array",
"items": {
"$ref": "../../type/basic.json#/definitions/uuid"
},
"default": null
}
},
"required": ["name", "teamType"],

View File

@ -102,6 +102,10 @@
"defaultRoles": {
"description": "Default roles of a team. These roles will be inherited by all the users that are part of this team.",
"$ref": "../../type/entityReference.json#/definitions/entityReferenceList"
},
"policies": {
"description": "Policies that is attached to this team.",
"$ref": "../../type/entityReference.json#/definitions/entityReferenceList"
}
},
"required": ["id", "name", "href"],

View File

@ -99,6 +99,7 @@ import org.openmetadata.catalog.entity.data.Database;
import org.openmetadata.catalog.entity.data.DatabaseSchema;
import org.openmetadata.catalog.entity.data.Glossary;
import org.openmetadata.catalog.entity.data.GlossaryTerm;
import org.openmetadata.catalog.entity.policies.Policy;
import org.openmetadata.catalog.entity.services.DashboardService;
import org.openmetadata.catalog.entity.services.DatabaseService;
import org.openmetadata.catalog.entity.services.MessagingService;
@ -117,6 +118,7 @@ import org.openmetadata.catalog.resources.events.EventResource.ChangeEventList;
import org.openmetadata.catalog.resources.events.WebhookResourceTest;
import org.openmetadata.catalog.resources.glossary.GlossaryResourceTest;
import org.openmetadata.catalog.resources.metadata.TypeResourceTest;
import org.openmetadata.catalog.resources.policies.PolicyResourceTest;
import org.openmetadata.catalog.resources.services.DashboardServiceResourceTest;
import org.openmetadata.catalog.resources.services.DatabaseServiceResourceTest;
import org.openmetadata.catalog.resources.services.MessagingServiceResourceTest;
@ -187,6 +189,9 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
public static Role ROLE1;
public static EntityReference ROLE1_REFERENCE;
public static Policy POLICY1;
public static Policy POLICY2;
public static EntityReference SNOWFLAKE_REFERENCE;
public static EntityReference REDSHIFT_REFERENCE;
public static EntityReference MYSQL_REFERENCE;
@ -285,6 +290,7 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
new DashboardServiceResourceTest().setupDashboardServices(test);
new MlModelServiceResourceTest().setupMlModelServices(test);
new TableResourceTest().setupDatabaseSchemas(test);
new PolicyResourceTest().setupPolicies();
}
@AfterAll

View File

@ -132,7 +132,7 @@ public class GlossaryResourceTest extends EntityResourceTest<Glossary, CreateGlo
throws HttpResponseException {
// Entity specific validation
TestUtils.validateTags(expected.getTags(), patched.getTags());
TestUtils.assertEntityReferenceList(expected.getReviewers(), patched.getReviewers());
TestUtils.assertEntityReferences(expected.getReviewers(), patched.getReviewers());
}
@Override

View File

@ -30,7 +30,7 @@ import static org.openmetadata.catalog.resources.databases.TableResourceTest.get
import static org.openmetadata.catalog.type.ColumnDataType.BIGINT;
import static org.openmetadata.catalog.util.TestUtils.ADMIN_AUTH_HEADERS;
import static org.openmetadata.catalog.util.TestUtils.UpdateType.MINOR_UPDATE;
import static org.openmetadata.catalog.util.TestUtils.assertEntityReferenceList;
import static org.openmetadata.catalog.util.TestUtils.assertEntityReferences;
import static org.openmetadata.catalog.util.TestUtils.assertListNotEmpty;
import static org.openmetadata.catalog.util.TestUtils.assertListNotNull;
import static org.openmetadata.catalog.util.TestUtils.assertListNull;
@ -326,8 +326,8 @@ public class GlossaryTermResourceTest extends EntityResourceTest<GlossaryTerm, C
assertEquals(expected.getFullyQualifiedName(), actual.getFullyQualifiedName());
assertEquals(expected.getSynonyms(), actual.getSynonyms());
assertEquals(expected.getParent(), actual.getParent());
assertEntityReferenceList(expected.getChildren(), actual.getChildren());
assertEntityReferenceList(expected.getReviewers(), actual.getReviewers());
TestUtils.assertEntityReferences(expected.getChildren(), actual.getChildren());
TestUtils.assertEntityReferences(expected.getReviewers(), actual.getReviewers());
TestUtils.validateTags(expected.getTags(), actual.getTags());
}
TestUtils.validateAlphabeticalOrdering(actualTerms, EntityUtil.compareGlossaryTerm);
@ -366,8 +366,8 @@ public class GlossaryTermResourceTest extends EntityResourceTest<GlossaryTerm, C
assertTrue(EntityUtil.entityReferenceMatch.test(request.getParent(), entity.getParent()));
}
assertEntityReferenceList(request.getRelatedTerms(), entity.getRelatedTerms());
assertEntityReferenceList(request.getReviewers(), entity.getReviewers());
TestUtils.assertEntityReferences(request.getRelatedTerms(), entity.getRelatedTerms());
TestUtils.assertEntityReferences(request.getReviewers(), entity.getReviewers());
// Entity specific validation
TestUtils.validateTags(request.getTags(), entity.getTags());

View File

@ -76,6 +76,11 @@ public class PolicyResourceTest extends EntityResourceTest<Policy, CreatePolicy>
location = createLocation();
}
public void setupPolicies() throws HttpResponseException {
POLICY1 = createEntity(createRequest("policy1"), ADMIN_AUTH_HEADERS);
POLICY2 = createEntity(createRequest("policy2"), ADMIN_AUTH_HEADERS);
}
@Override
public CreatePolicy createRequest(String name) {
return new CreatePolicy().withName(name).withPolicyType(PolicyType.Lifecycle);

View File

@ -23,7 +23,6 @@ import static org.openmetadata.catalog.util.TestUtils.ADMIN_AUTH_HEADERS;
import static org.openmetadata.catalog.util.TestUtils.TEST_AUTH_HEADERS;
import static org.openmetadata.catalog.util.TestUtils.TEST_USER_NAME;
import static org.openmetadata.catalog.util.TestUtils.UpdateType.MINOR_UPDATE;
import static org.openmetadata.catalog.util.TestUtils.assertEntityReferenceList;
import static org.openmetadata.catalog.util.TestUtils.assertListNotNull;
import static org.openmetadata.catalog.util.TestUtils.assertListNull;
import static org.openmetadata.catalog.util.TestUtils.assertResponse;
@ -230,7 +229,7 @@ public class RoleResourceTest extends EntityResourceTest<Role, CreateRole> {
@Override
public void validateCreatedEntity(Role role, CreateRole createRequest, Map<String, String> authHeaders) {
assertEntityReferenceList(role.getPolicies(), createRequest.getPolicies());
TestUtils.assertEntityReferences(role.getPolicies(), createRequest.getPolicies());
}
@Override

View File

@ -416,6 +416,258 @@ public class TeamResourceTest extends EntityResourceTest<Team, CreateTeam> {
patchEntityAndCheck(bu2, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change2);
}
@Test
void patch_isJoinable_200(TestInfo test) throws IOException {
CreateTeam create =
createRequest(getEntityName(test), "description", "displayName", null)
.withProfile(PROFILE)
.withIsJoinable(false);
Team team = createAndCheckEntity(create, ADMIN_AUTH_HEADERS);
// patch the team with isJoinable set to true
String json = JsonUtils.pojoToJson(team);
team.setIsJoinable(true);
ChangeDescription change = getChangeDescription(team.getVersion());
change.getFieldsUpdated().add(new FieldChange().withName("isJoinable").withOldValue(false).withNewValue(true));
team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change);
// set isJoinable to false and check
json = JsonUtils.pojoToJson(team);
team.setIsJoinable(false);
change = getChangeDescription(team.getVersion());
change.getFieldsUpdated().add(new FieldChange().withName("isJoinable").withOldValue(true).withNewValue(false));
patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change);
}
@Test
void patch_deleteUserAndDefaultRoleFromTeam_200(TestInfo test) throws IOException {
UserResourceTest userResourceTest = new UserResourceTest();
final int totalUsers = 20;
ArrayList<UUID> users = new ArrayList<>();
for (int i = 0; i < totalUsers; i++) {
User user = userResourceTest.createEntity(userResourceTest.createRequest(test, i), ADMIN_AUTH_HEADERS);
users.add(user.getId());
}
RoleResourceTest roleResourceTest = new RoleResourceTest();
roleResourceTest.createRolesAndSetDefault(test, 5, 0);
List<Role> roles = roleResourceTest.listEntities(Map.of(), ADMIN_AUTH_HEADERS).getData();
List<UUID> rolesIds = roles.stream().map(Role::getId).collect(Collectors.toList());
CreateTeam create =
createRequest(getEntityName(test), "description", "displayName", null)
.withProfile(PROFILE)
.withUsers(users)
.withDefaultRoles(rolesIds);
Team team = createAndCheckEntity(create, ADMIN_AUTH_HEADERS);
// Remove a user from the team using patch request
String json = JsonUtils.pojoToJson(team);
int removeUserIndex = new Random().nextInt(totalUsers);
EntityReference deletedUser = team.getUsers().get(removeUserIndex);
team.getUsers().remove(removeUserIndex);
ChangeDescription change = getChangeDescription(team.getVersion());
change.getFieldsDeleted().add(new FieldChange().withName("users").withOldValue(Arrays.asList(deletedUser)));
team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change);
// Remove a default role from the team using patch request
json = JsonUtils.pojoToJson(team);
int removeDefaultRoleIndex = new Random().nextInt(roles.size());
EntityReference deletedRole = team.getDefaultRoles().get(removeDefaultRoleIndex);
team.getDefaultRoles().remove(removeDefaultRoleIndex);
change = getChangeDescription(team.getVersion());
change.getFieldsDeleted().add(new FieldChange().withName("defaultRoles").withOldValue(Arrays.asList(deletedRole)));
patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change);
}
@Test
void post_teamWithPolicies(TestInfo test) throws IOException {
System.out.println("XXX " + POLICY1);
System.out.println("XXX " + POLICY2);
CreateTeam create = createRequest(getEntityName(test)).withPolicies(List.of(POLICY1.getId(), POLICY2.getId()));
createAndCheckEntity(create, ADMIN_AUTH_HEADERS);
}
@Test
void put_teamWithPolicies(TestInfo test) throws IOException {
CreateTeam create = createRequest(getEntityName(test));
Team team = createAndCheckEntity(create, ADMIN_AUTH_HEADERS);
// Add policies to the team
create = createRequest(getEntityName(test)).withPolicies(List.of(POLICY1.getId(), POLICY2.getId()));
ChangeDescription change = getChangeDescription(team.getVersion());
change
.getFieldsAdded()
.add(
new FieldChange()
.withName("policies")
.withNewValue(List.of(POLICY1.getEntityReference(), POLICY2.getEntityReference())));
team = updateAndCheckEntity(create, OK, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Remove policies from the team
create = createRequest(getEntityName(test));
change = getChangeDescription(team.getVersion());
change
.getFieldsDeleted()
.add(
new FieldChange()
.withName("policies")
.withOldValue(List.of(POLICY1.getEntityReference(), POLICY2.getEntityReference())));
updateAndCheckEntity(create, OK, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
@Test
void patch_teamWithPolicies(TestInfo test) throws IOException {
CreateTeam create = createRequest(getEntityName(test));
Team team = createAndCheckEntity(create, ADMIN_AUTH_HEADERS);
// Add policies to the team
String json = JsonUtils.pojoToJson(team);
team.withPolicies(List.of(POLICY1.getEntityReference(), POLICY2.getEntityReference()));
ChangeDescription change = getChangeDescription(team.getVersion());
change
.getFieldsAdded()
.add(
new FieldChange()
.withName("policies")
.withNewValue(List.of(POLICY1.getEntityReference(), POLICY2.getEntityReference())));
team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
// Remove policies from the team
json = JsonUtils.pojoToJson(team);
team.withPolicies(null);
change = getChangeDescription(team.getVersion());
change
.getFieldsDeleted()
.add(
new FieldChange()
.withName("policies")
.withOldValue(List.of(POLICY1.getEntityReference(), POLICY2.getEntityReference())));
patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
}
private static void validateTeam(
Team team,
String expectedDescription,
String expectedDisplayName,
Profile expectedProfile,
List<EntityReference> expectedUsers,
List<EntityReference> expectedDefaultRoles,
String expectedUpdatedBy) {
assertListNotNull(team.getId(), team.getHref());
assertEquals(expectedDescription, team.getDescription());
assertEquals(expectedUpdatedBy, team.getUpdatedBy());
assertEquals(expectedDisplayName, team.getDisplayName());
assertEquals(expectedProfile, team.getProfile());
TestUtils.assertEntityReferences(expectedUsers, team.getUsers());
TestUtils.assertEntityReferences(expectedDefaultRoles, team.getDefaultRoles());
validateEntityReferences(team.getOwns());
}
@Override
public Team validateGetWithDifferentFields(Team expectedTeam, boolean byName) throws HttpResponseException {
if (expectedTeam.getUsers() == null) {
UserResourceTest userResourceTest = new UserResourceTest();
CreateUser create = userResourceTest.createRequest("user", "", "", null).withTeams(List.of(expectedTeam.getId()));
userResourceTest.createEntity(create, ADMIN_AUTH_HEADERS);
}
String updatedBy = getPrincipalName(ADMIN_AUTH_HEADERS);
String fields = "";
Team getTeam =
byName
? getEntityByName(expectedTeam.getName(), fields, ADMIN_AUTH_HEADERS)
: getEntity(expectedTeam.getId(), null, fields, ADMIN_AUTH_HEADERS);
validateTeam(getTeam, expectedTeam.getDescription(), expectedTeam.getDisplayName(), null, null, null, updatedBy);
assertNull(getTeam.getOwns());
fields = "users,owns,profile,defaultRoles,owner";
getTeam =
byName
? getEntityByName(expectedTeam.getName(), fields, ADMIN_AUTH_HEADERS)
: getEntity(expectedTeam.getId(), fields, ADMIN_AUTH_HEADERS);
assertNotNull(getTeam.getProfile());
validateEntityReferences(getTeam.getOwns());
validateEntityReferences(getTeam.getUsers(), true);
validateEntityReferences(getTeam.getDefaultRoles());
return getTeam;
}
@Override
public CreateTeam createRequest(String name) {
return new CreateTeam().withName(name).withProfile(PROFILE);
}
@Override
public Team beforeDeletion(TestInfo test, Team team) throws HttpResponseException {
LocationResourceTest locationResourceTest = new LocationResourceTest();
EntityReference teamRef = new EntityReference().withId(team.getId()).withType("team");
locationResourceTest.createEntity(
locationResourceTest.createRequest(getEntityName(test), null, null, teamRef), ADMIN_AUTH_HEADERS);
return team;
}
@Override
public void validateCreatedEntity(Team team, CreateTeam createRequest, Map<String, String> authHeaders) {
assertEquals(createRequest.getProfile(), team.getProfile());
TestUtils.validateEntityReferences(team.getOwns());
List<EntityReference> expectedUsers = new ArrayList<>();
for (UUID userId : listOrEmpty(createRequest.getUsers())) {
expectedUsers.add(new EntityReference().withId(userId).withType(Entity.USER));
}
expectedUsers = expectedUsers.isEmpty() ? null : expectedUsers;
TestUtils.assertEntityReferences(expectedUsers, team.getUsers());
TestUtils.assertEntityReferenceIds(createRequest.getDefaultRoles(), team.getDefaultRoles());
System.out.println("XXX " + team.getParents());
TestUtils.assertEntityReferenceIds(createRequest.getParents(), team.getParents());
TestUtils.assertEntityReferenceIds(createRequest.getChildren(), team.getChildren());
TestUtils.assertEntityReferenceIds(createRequest.getPolicies(), team.getPolicies());
}
@Override
protected void validateDeletedEntity(
CreateTeam create, Team teamBeforeDeletion, Team teamAfterDeletion, Map<String, String> authHeaders)
throws HttpResponseException {
super.validateDeletedEntity(create, teamBeforeDeletion, teamAfterDeletion, authHeaders);
List<EntityReference> expectedOwnedEntities = new ArrayList<>();
for (EntityReference ref : listOrEmpty(teamBeforeDeletion.getOwns())) {
expectedOwnedEntities.add(new EntityReference().withId(ref.getId()).withType(Entity.TABLE));
}
TestUtils.assertEntityReferences(expectedOwnedEntities, teamAfterDeletion.getOwns());
}
@Override
public void compareEntities(Team expected, Team updated, Map<String, String> authHeaders) {
assertEquals(expected.getDisplayName(), updated.getDisplayName());
assertEquals(expected.getProfile(), updated.getProfile());
TestUtils.validateEntityReferences(updated.getOwns());
List<EntityReference> expectedUsers = listOrEmpty(expected.getUsers());
List<EntityReference> actualUsers = listOrEmpty(updated.getUsers());
TestUtils.assertEntityReferences(expectedUsers, actualUsers);
List<EntityReference> expectedDefaultRoles = listOrEmpty(expected.getDefaultRoles());
List<EntityReference> actualDefaultRoles = listOrEmpty(updated.getDefaultRoles());
TestUtils.assertEntityReferences(expectedDefaultRoles, actualDefaultRoles);
}
@Override
public void assertFieldChange(String fieldName, Object expected, Object actual) throws IOException {
if (expected == actual) {
return;
}
if (List.of("users", "defaultRoles", "parents", "children", "policies").contains(fieldName)) {
@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);
}
}
private Team createWithParents(String teamName, TeamType teamType, EntityReference... parents)
throws HttpResponseException {
List<EntityReference> parentList = List.of(parents);
@ -488,192 +740,4 @@ public class TeamResourceTest extends EntityResourceTest<Team, CreateTeam> {
.withRoles(List.of(teamManager.getId())),
ADMIN_AUTH_HEADERS);
}
@Test
void patch_isJoinable_200(TestInfo test) throws IOException {
CreateTeam create =
createRequest(getEntityName(test), "description", "displayName", null)
.withProfile(PROFILE)
.withIsJoinable(false);
Team team = createAndCheckEntity(create, ADMIN_AUTH_HEADERS);
// patch the team with isJoinable set to true
String json = JsonUtils.pojoToJson(team);
team.setIsJoinable(true);
ChangeDescription change = getChangeDescription(team.getVersion());
change.getFieldsUpdated().add(new FieldChange().withName("isJoinable").withOldValue(false).withNewValue(true));
team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change);
// set isJoinable to false and check
json = JsonUtils.pojoToJson(team);
team.setIsJoinable(false);
change = getChangeDescription(team.getVersion());
change.getFieldsUpdated().add(new FieldChange().withName("isJoinable").withOldValue(true).withNewValue(false));
patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change);
}
@Test
void patch_deleteUserAndDefaultRoleFromTeam_200(TestInfo test) throws IOException {
UserResourceTest userResourceTest = new UserResourceTest();
final int totalUsers = 20;
ArrayList<UUID> users = new ArrayList<>();
for (int i = 0; i < totalUsers; i++) {
User user = userResourceTest.createEntity(userResourceTest.createRequest(test, i), ADMIN_AUTH_HEADERS);
users.add(user.getId());
}
RoleResourceTest roleResourceTest = new RoleResourceTest();
roleResourceTest.createRolesAndSetDefault(test, 5, 0);
List<Role> roles = roleResourceTest.listEntities(Map.of(), ADMIN_AUTH_HEADERS).getData();
List<UUID> rolesIds = roles.stream().map(Role::getId).collect(Collectors.toList());
CreateTeam create =
createRequest(getEntityName(test), "description", "displayName", null)
.withProfile(PROFILE)
.withUsers(users)
.withDefaultRoles(rolesIds);
Team team = createAndCheckEntity(create, ADMIN_AUTH_HEADERS);
// Remove a user from the team using patch request
String json = JsonUtils.pojoToJson(team);
int removeUserIndex = new Random().nextInt(totalUsers);
EntityReference deletedUser = team.getUsers().get(removeUserIndex);
team.getUsers().remove(removeUserIndex);
ChangeDescription change = getChangeDescription(team.getVersion());
change.getFieldsDeleted().add(new FieldChange().withName("users").withOldValue(Arrays.asList(deletedUser)));
team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change);
// Remove a default role from the team using patch request
json = JsonUtils.pojoToJson(team);
int removeDefaultRoleIndex = new Random().nextInt(roles.size());
EntityReference deletedRole = team.getDefaultRoles().get(removeDefaultRoleIndex);
team.getDefaultRoles().remove(removeDefaultRoleIndex);
change = getChangeDescription(team.getVersion());
change.getFieldsDeleted().add(new FieldChange().withName("defaultRoles").withOldValue(Arrays.asList(deletedRole)));
patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change);
}
private static void validateTeam(
Team team,
String expectedDescription,
String expectedDisplayName,
Profile expectedProfile,
List<EntityReference> expectedUsers,
List<EntityReference> expectedDefaultRoles,
String expectedUpdatedBy) {
assertListNotNull(team.getId(), team.getHref());
assertEquals(expectedDescription, team.getDescription());
assertEquals(expectedUpdatedBy, team.getUpdatedBy());
assertEquals(expectedDisplayName, team.getDisplayName());
assertEquals(expectedProfile, team.getProfile());
TestUtils.assertEntityReferenceList(expectedUsers, team.getUsers());
TestUtils.assertEntityReferenceList(expectedDefaultRoles, team.getDefaultRoles());
validateEntityReferences(team.getOwns());
}
@Override
public Team validateGetWithDifferentFields(Team expectedTeam, boolean byName) throws HttpResponseException {
if (expectedTeam.getUsers() == null) {
UserResourceTest userResourceTest = new UserResourceTest();
CreateUser create = userResourceTest.createRequest("user", "", "", null).withTeams(List.of(expectedTeam.getId()));
userResourceTest.createEntity(create, ADMIN_AUTH_HEADERS);
}
String updatedBy = getPrincipalName(ADMIN_AUTH_HEADERS);
String fields = "";
Team getTeam =
byName
? getEntityByName(expectedTeam.getName(), fields, ADMIN_AUTH_HEADERS)
: getEntity(expectedTeam.getId(), null, fields, ADMIN_AUTH_HEADERS);
validateTeam(getTeam, expectedTeam.getDescription(), expectedTeam.getDisplayName(), null, null, null, updatedBy);
assertNull(getTeam.getOwns());
fields = "users,owns,profile,defaultRoles,owner";
getTeam =
byName
? getEntityByName(expectedTeam.getName(), fields, ADMIN_AUTH_HEADERS)
: getEntity(expectedTeam.getId(), fields, ADMIN_AUTH_HEADERS);
assertNotNull(getTeam.getProfile());
validateEntityReferences(getTeam.getOwns());
validateEntityReferences(getTeam.getUsers(), true);
validateEntityReferences(getTeam.getDefaultRoles());
return getTeam;
}
@Override
public CreateTeam createRequest(String name) {
return new CreateTeam().withName(name).withProfile(PROFILE);
}
@Override
public Team beforeDeletion(TestInfo test, Team team) throws HttpResponseException {
LocationResourceTest locationResourceTest = new LocationResourceTest();
EntityReference teamRef = new EntityReference().withId(team.getId()).withType("team");
locationResourceTest.createEntity(
locationResourceTest.createRequest(getEntityName(test), null, null, teamRef), ADMIN_AUTH_HEADERS);
return team;
}
@Override
public void validateCreatedEntity(Team team, CreateTeam createRequest, Map<String, String> authHeaders) {
assertEquals(createRequest.getProfile(), team.getProfile());
TestUtils.validateEntityReferences(team.getOwns());
List<EntityReference> expectedUsers = new ArrayList<>();
for (UUID userId : listOrEmpty(createRequest.getUsers())) {
expectedUsers.add(new EntityReference().withId(userId).withType(Entity.USER));
}
expectedUsers = expectedUsers.isEmpty() ? null : expectedUsers;
TestUtils.assertEntityReferenceList(expectedUsers, team.getUsers());
List<EntityReference> expectedDefaultRoles = new ArrayList<>();
for (UUID roleId : listOrEmpty(createRequest.getDefaultRoles())) {
expectedDefaultRoles.add(new EntityReference().withId(roleId).withType(Entity.ROLE));
}
expectedDefaultRoles = expectedDefaultRoles.isEmpty() ? null : expectedDefaultRoles;
TestUtils.assertEntityReferenceList(expectedDefaultRoles, team.getDefaultRoles());
}
@Override
protected void validateDeletedEntity(
CreateTeam create, Team teamBeforeDeletion, Team teamAfterDeletion, Map<String, String> authHeaders)
throws HttpResponseException {
super.validateDeletedEntity(create, teamBeforeDeletion, teamAfterDeletion, authHeaders);
List<EntityReference> expectedOwnedEntities = new ArrayList<>();
for (EntityReference ref : listOrEmpty(teamBeforeDeletion.getOwns())) {
expectedOwnedEntities.add(new EntityReference().withId(ref.getId()).withType(Entity.TABLE));
}
TestUtils.assertEntityReferenceList(expectedOwnedEntities, teamAfterDeletion.getOwns());
}
@Override
public void compareEntities(Team expected, Team updated, Map<String, String> authHeaders) {
assertEquals(expected.getDisplayName(), updated.getDisplayName());
assertEquals(expected.getProfile(), updated.getProfile());
TestUtils.validateEntityReferences(updated.getOwns());
List<EntityReference> expectedUsers = listOrEmpty(expected.getUsers());
List<EntityReference> actualUsers = listOrEmpty(updated.getUsers());
TestUtils.assertEntityReferenceList(expectedUsers, actualUsers);
List<EntityReference> expectedDefaultRoles = listOrEmpty(expected.getDefaultRoles());
List<EntityReference> actualDefaultRoles = listOrEmpty(updated.getDefaultRoles());
TestUtils.assertEntityReferenceList(expectedDefaultRoles, actualDefaultRoles);
}
@Override
public void assertFieldChange(String fieldName, Object expected, Object actual) throws IOException {
if (expected == actual) {
return;
}
if (List.of("users", "defaultRoles", "parents", "children").contains(fieldName)) {
@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);
}
}
}

View File

@ -35,7 +35,7 @@ import static org.openmetadata.catalog.util.TestUtils.TEST_AUTH_HEADERS;
import static org.openmetadata.catalog.util.TestUtils.TEST_USER_NAME;
import static org.openmetadata.catalog.util.TestUtils.UpdateType.MINOR_UPDATE;
import static org.openmetadata.catalog.util.TestUtils.assertDeleted;
import static org.openmetadata.catalog.util.TestUtils.assertEntityReferenceList;
import static org.openmetadata.catalog.util.TestUtils.assertEntityReferences;
import static org.openmetadata.catalog.util.TestUtils.assertListNotNull;
import static org.openmetadata.catalog.util.TestUtils.assertListNull;
import static org.openmetadata.catalog.util.TestUtils.assertResponse;
@ -753,8 +753,8 @@ public class UserResourceTest extends EntityResourceTest<User, CreateUser> {
private void assertRoles(
User user, List<EntityReference> expectedRoles, List<EntityReference> expectedInheritedRoles) {
assertEntityReferenceList(expectedRoles, user.getRoles());
assertEntityReferenceList(expectedInheritedRoles, user.getInheritedRoles());
TestUtils.assertEntityReferences(expectedRoles, user.getRoles());
TestUtils.assertEntityReferences(expectedInheritedRoles, user.getInheritedRoles());
}
@Override
@ -806,7 +806,7 @@ public class UserResourceTest extends EntityResourceTest<User, CreateUser> {
expectedOwnedEntities.add(new EntityReference().withId(ref.getId()).withType(Entity.TABLE));
}
TestUtils.assertEntityReferenceList(expectedOwnedEntities, userAfterDeletion.getOwns());
TestUtils.assertEntityReferences(expectedOwnedEntities, userAfterDeletion.getOwns());
}
@Override
@ -828,7 +828,7 @@ public class UserResourceTest extends EntityResourceTest<User, CreateUser> {
for (UUID teamId : listOrEmpty(createRequest.getTeams())) {
expectedTeams.add(new EntityReference().withId(teamId).withType(Entity.TEAM));
}
TestUtils.assertEntityReferenceList(expectedTeams, user.getTeams());
TestUtils.assertEntityReferences(expectedTeams, user.getTeams());
if (createRequest.getProfile() != null) {
assertEquals(createRequest.getProfile(), user.getProfile());
@ -843,8 +843,8 @@ public class UserResourceTest extends EntityResourceTest<User, CreateUser> {
assertEquals(expected.getIsBot(), expected.getIsBot());
assertEquals(expected.getIsAdmin(), expected.getIsAdmin());
assertEntityReferenceList(expected.getRoles(), updated.getRoles());
assertEntityReferenceList(expected.getTeams(), updated.getTeams());
TestUtils.assertEntityReferences(expected.getRoles(), updated.getRoles());
TestUtils.assertEntityReferences(expected.getTeams(), updated.getTeams());
if (expected.getProfile() != null) {
assertEquals(expected.getProfile(), updated.getProfile());

View File

@ -391,7 +391,22 @@ public final class TestUtils {
}
}
public static void assertEntityReferenceList(List<EntityReference> expected, List<EntityReference> actual) {
public static void assertEntityReferenceIds(List<UUID> expected, List<EntityReference> actual) {
if (expected == null && actual == null) {
return;
}
if (listOrEmpty(expected).isEmpty()) {
return;
}
for (UUID id : listOrEmpty(expected)) {
actual = listOrEmpty(actual);
assertEquals(expected.size(), actual.size());
assertNotNull(actual.stream().filter(entity -> entity.getId().equals(id)).findAny().get());
}
validateEntityReferences(actual);
}
public static void assertEntityReferences(List<EntityReference> expected, List<EntityReference> actual) {
if (expected == actual) { // Take care of both being null
return;
}

View File

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