Fixed#11286: mutually exclusive tags addition check is not working for some entities (#11331)

* Fixed#11286: mutually exclusive tags addition check is not working for some entities

* Fixed#11286: mutually exclusive tags addition check is not working for some entities

* Fixed#11286: mutually exclusive tags addition check is not working for some entities

---------

Co-authored-by: Mohit Yadav <105265192+mohityadav766@users.noreply.github.com>
This commit is contained in:
Parth Panchal 2023-05-02 09:04:33 +05:30 committed by GitHub
parent 1546e78dbc
commit 6cc448c071
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 90 additions and 0 deletions

View File

@ -68,6 +68,9 @@ public class DashboardDataModelRepository extends EntityRepository<DashboardData
DashboardService dashboardService = Entity.getEntity(dashboardDataModel.getService(), "", Include.ALL); DashboardService dashboardService = Entity.getEntity(dashboardDataModel.getService(), "", Include.ALL);
dashboardDataModel.setService(dashboardService.getEntityReference()); dashboardDataModel.setService(dashboardService.getEntityReference());
dashboardDataModel.setServiceType(dashboardService.getServiceType()); dashboardDataModel.setServiceType(dashboardService.getServiceType());
// Validate column tags
validateColumnTags(dashboardDataModel.getColumns());
} }
@Override @Override
@ -159,6 +162,15 @@ public class DashboardDataModelRepository extends EntityRepository<DashboardData
return new DataModelUpdater(original, updated, operation); return new DataModelUpdater(original, updated, operation);
} }
private void validateColumnTags(List<Column> columns) {
for (Column column : columns) {
checkMutuallyExclusive(column.getTags());
if (column.getChildren() != null) {
validateColumnTags(column.getChildren());
}
}
}
public class DataModelUpdater extends ColumnEntityUpdater { public class DataModelUpdater extends ColumnEntityUpdater {
public DataModelUpdater(DashboardDataModel original, DashboardDataModel updated, Operation operation) { public DataModelUpdater(DashboardDataModel original, DashboardDataModel updated, Operation operation) {

View File

@ -131,6 +131,7 @@ public class MlModelRepository extends EntityRepository<MlModel> {
populateService(mlModel); populateService(mlModel);
if (!nullOrEmpty(mlModel.getMlFeatures())) { if (!nullOrEmpty(mlModel.getMlFeatures())) {
validateReferences(mlModel.getMlFeatures()); validateReferences(mlModel.getMlFeatures());
mlModel.getMlFeatures().forEach(feature -> checkMutuallyExclusive(feature.getTags()));
} }
// Check that the dashboard exists // Check that the dashboard exists

View File

@ -16,6 +16,10 @@ package org.openmetadata.service.resources.datamodels;
import static javax.ws.rs.core.Response.Status.BAD_REQUEST; import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.openmetadata.common.utils.CommonUtil.listOf;
import static org.openmetadata.schema.type.ColumnDataType.INT;
import static org.openmetadata.schema.type.ColumnDataType.STRUCT;
import static org.openmetadata.service.resources.databases.TableResourceTest.getColumn;
import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS; import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS;
import static org.openmetadata.service.util.TestUtils.assertListNotEmpty; import static org.openmetadata.service.util.TestUtils.assertListNotEmpty;
import static org.openmetadata.service.util.TestUtils.assertListNotNull; import static org.openmetadata.service.util.TestUtils.assertListNotNull;
@ -24,6 +28,7 @@ import static org.openmetadata.service.util.TestUtils.assertResponse;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.HttpResponseException; import org.apache.http.client.HttpResponseException;
@ -33,9 +38,11 @@ import org.junit.jupiter.api.parallel.Execution;
import org.junit.jupiter.api.parallel.ExecutionMode; import org.junit.jupiter.api.parallel.ExecutionMode;
import org.openmetadata.schema.api.data.CreateDashboardDataModel; import org.openmetadata.schema.api.data.CreateDashboardDataModel;
import org.openmetadata.schema.entity.data.DashboardDataModel; import org.openmetadata.schema.entity.data.DashboardDataModel;
import org.openmetadata.schema.type.Column;
import org.openmetadata.schema.type.DataModelType; import org.openmetadata.schema.type.DataModelType;
import org.openmetadata.schema.type.EntityReference; import org.openmetadata.schema.type.EntityReference;
import org.openmetadata.service.Entity; import org.openmetadata.service.Entity;
import org.openmetadata.service.exception.CatalogExceptionMessage;
import org.openmetadata.service.resources.EntityResourceTest; import org.openmetadata.service.resources.EntityResourceTest;
import org.openmetadata.service.util.ResultList; import org.openmetadata.service.util.ResultList;
@ -80,6 +87,34 @@ public class DashboardDataModelResourceTest extends EntityResourceTest<Dashboard
} }
} }
@Test
void test_mutuallyExclusiveTags(TestInfo testInfo) {
CreateDashboardDataModel create = createRequest(testInfo).withTags(List.of(TIER1_TAG_LABEL, TIER2_TAG_LABEL));
assertResponse(
() -> createEntity(create, ADMIN_AUTH_HEADERS),
BAD_REQUEST,
CatalogExceptionMessage.mutuallyExclusiveLabels(TIER2_TAG_LABEL, TIER1_TAG_LABEL));
// Apply mutually exclusive tags to a dataModel column
CreateDashboardDataModel createDashboardDataModel = createRequest(testInfo, 1);
Column column = getColumn("test", INT, null).withTags(listOf(TIER1_TAG_LABEL, TIER2_TAG_LABEL));
createDashboardDataModel.setColumns(listOf(column));
assertResponse(
() -> createEntity(createDashboardDataModel, ADMIN_AUTH_HEADERS),
BAD_REQUEST,
CatalogExceptionMessage.mutuallyExclusiveLabels(TIER2_TAG_LABEL, TIER1_TAG_LABEL));
// Apply mutually exclusive tags to a dataModel's nested column
CreateDashboardDataModel createDashboardDataModel1 = createRequest(testInfo, 1);
Column nestedColumns = getColumn("testNested", INT, null).withTags(listOf(TIER1_TAG_LABEL, TIER2_TAG_LABEL));
Column column1 = getColumn("test", STRUCT, null).withChildren(List.of(nestedColumns));
createDashboardDataModel1.setColumns(listOf(column1));
assertResponse(
() -> createEntity(createDashboardDataModel1, ADMIN_AUTH_HEADERS),
BAD_REQUEST,
CatalogExceptionMessage.mutuallyExclusiveLabels(TIER2_TAG_LABEL, TIER1_TAG_LABEL));
}
@Override @Override
@Execution(ExecutionMode.CONCURRENT) @Execution(ExecutionMode.CONCURRENT)
public DashboardDataModel validateGetWithDifferentFields(DashboardDataModel dashboardDataModel, boolean byName) public DashboardDataModel validateGetWithDifferentFields(DashboardDataModel dashboardDataModel, boolean byName)

View File

@ -13,8 +13,10 @@
package org.openmetadata.service.resources.mlmodels; package org.openmetadata.service.resources.mlmodels;
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.openmetadata.common.utils.CommonUtil.listOf;
import static org.openmetadata.service.util.EntityUtil.fieldAdded; import static org.openmetadata.service.util.EntityUtil.fieldAdded;
import static org.openmetadata.service.util.EntityUtil.fieldDeleted; import static org.openmetadata.service.util.EntityUtil.fieldDeleted;
import static org.openmetadata.service.util.EntityUtil.fieldUpdated; import static org.openmetadata.service.util.EntityUtil.fieldUpdated;
@ -57,6 +59,7 @@ import org.openmetadata.schema.type.MlFeatureSource;
import org.openmetadata.schema.type.MlHyperParameter; import org.openmetadata.schema.type.MlHyperParameter;
import org.openmetadata.schema.type.MlStore; import org.openmetadata.schema.type.MlStore;
import org.openmetadata.service.Entity; import org.openmetadata.service.Entity;
import org.openmetadata.service.exception.CatalogExceptionMessage;
import org.openmetadata.service.resources.EntityResourceTest; import org.openmetadata.service.resources.EntityResourceTest;
import org.openmetadata.service.resources.dashboards.DashboardResourceTest; import org.openmetadata.service.resources.dashboards.DashboardResourceTest;
import org.openmetadata.service.resources.databases.TableResourceTest; import org.openmetadata.service.resources.databases.TableResourceTest;
@ -83,12 +86,14 @@ public class MlModelResourceTest extends EntityResourceTest<MlModel, CreateMlMod
public static final List<MlFeature> ML_FEATURES = public static final List<MlFeature> ML_FEATURES =
Arrays.asList( Arrays.asList(
new MlFeature() new MlFeature()
.withTags(null)
.withName("age") .withName("age")
.withDataType(MlFeatureDataType.Numerical) .withDataType(MlFeatureDataType.Numerical)
.withFeatureSources( .withFeatureSources(
Collections.singletonList( Collections.singletonList(
new MlFeatureSource().withName("age").withDataType(FeatureSourceDataType.INTEGER))), new MlFeatureSource().withName("age").withDataType(FeatureSourceDataType.INTEGER))),
new MlFeature() new MlFeature()
.withTags(null)
.withName("persona") .withName("persona")
.withDataType(MlFeatureDataType.Categorical) .withDataType(MlFeatureDataType.Categorical)
.withFeatureSources( .withFeatureSources(
@ -341,6 +346,43 @@ public class MlModelResourceTest extends EntityResourceTest<MlModel, CreateMlMod
updateAndCheckEntity(request.withTarget("newTarget"), Status.OK, ADMIN_AUTH_HEADERS, MAJOR_UPDATE, change); updateAndCheckEntity(request.withTarget("newTarget"), Status.OK, ADMIN_AUTH_HEADERS, MAJOR_UPDATE, change);
} }
@Test
void test_mutuallyExclusiveTags(TestInfo testInfo) {
CreateMlModel create = createRequest(testInfo).withTags(List.of(TIER1_TAG_LABEL, TIER2_TAG_LABEL));
assertResponse(
() -> createEntity(create, ADMIN_AUTH_HEADERS),
BAD_REQUEST,
CatalogExceptionMessage.mutuallyExclusiveLabels(TIER2_TAG_LABEL, TIER1_TAG_LABEL));
List<MlFeature> mlFeatureList =
Arrays.asList(
new MlFeature()
.withTags(null)
.withName("age")
.withDataType(MlFeatureDataType.Numerical)
.withFeatureSources(
Collections.singletonList(
new MlFeatureSource().withName("age").withDataType(FeatureSourceDataType.INTEGER))),
new MlFeature()
.withTags(null)
.withName("persona")
.withDataType(MlFeatureDataType.Categorical)
.withFeatureSources(
Arrays.asList(
new MlFeatureSource().withName("age").withDataType(FeatureSourceDataType.INTEGER),
new MlFeatureSource().withName("education").withDataType(FeatureSourceDataType.STRING)))
.withFeatureAlgorithm("PCA"));
// Apply mutually exclusive tags to a MlModel feature
CreateMlModel createMlModel = createRequest(testInfo, 1);
for (MlFeature mlFeature : mlFeatureList) {
mlFeature.withTags(listOf(TIER1_TAG_LABEL, TIER2_TAG_LABEL));
}
createMlModel.setMlFeatures(mlFeatureList);
assertResponse(
() -> createEntity(createMlModel, ADMIN_AUTH_HEADERS),
BAD_REQUEST,
CatalogExceptionMessage.mutuallyExclusiveLabels(TIER2_TAG_LABEL, TIER1_TAG_LABEL));
}
@Override @Override
public MlModel validateGetWithDifferentFields(MlModel model, boolean byName) throws HttpResponseException { public MlModel validateGetWithDifferentFields(MlModel model, boolean byName) throws HttpResponseException {
// .../models?fields=owner // .../models?fields=owner