diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/DashboardServiceRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/DashboardServiceRepository.java index b64b0a6eccc..f0f1e16bf36 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/DashboardServiceRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/DashboardServiceRepository.java @@ -214,6 +214,9 @@ public class DashboardServiceRepository extends EntityRepository private void updateIngestionSchedule() throws JsonProcessingException { Schedule origSchedule = original.getEntity().getIngestionSchedule(); Schedule updatedSchedule = updated.getEntity().getIngestionSchedule(); - recordChange("ingestionSchedule", origSchedule, updatedSchedule); + recordChange("ingestionSchedule", origSchedule, updatedSchedule, true); } } } \ No newline at end of file diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/MessagingServiceRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/MessagingServiceRepository.java index f3beb227a90..d9143760caf 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/MessagingServiceRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/MessagingServiceRepository.java @@ -34,6 +34,7 @@ import org.openmetadata.catalog.util.JsonUtils; import java.io.IOException; import java.net.URI; import java.text.ParseException; +import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.UUID; @@ -199,6 +200,7 @@ public class MessagingServiceRepository extends EntityRepository origBrokers = original.getEntity().getBrokers(); + List updatedBrokers = updated.getEntity().getBrokers(); + + List addedBrokers = new ArrayList<>(); + List deletedBrokers = new ArrayList<>(); + recordListChange("brokers", origBrokers, updatedBrokers, addedBrokers, deletedBrokers, EntityUtil.stringMatch); } } } \ No newline at end of file diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PipelineServiceRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PipelineServiceRepository.java index 954109df4bd..3eba2856623 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PipelineServiceRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PipelineServiceRepository.java @@ -201,18 +201,14 @@ public class PipelineServiceRepository extends EntityRepository @Override public void entitySpecificUpdate() throws IOException { - updatePipelineUrl(); - updateIngestionSchedule(); - } - - private void updatePipelineUrl() throws JsonProcessingException { recordChange("pipelineUrl", original.getEntity().getPipelineUrl(), updated.getEntity().getPipelineUrl()); + updateIngestionSchedule(); } private void updateIngestionSchedule() throws JsonProcessingException { Schedule origSchedule = original.getEntity().getIngestionSchedule(); Schedule updatedSchedule = updated.getEntity().getIngestionSchedule(); - recordChange("ingestionSchedule", origSchedule, updatedSchedule); + recordChange("ingestionSchedule", origSchedule, updatedSchedule, true); } } } \ No newline at end of file diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/services/dashboard/DashboardServiceResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/services/dashboard/DashboardServiceResource.java index 91590fee222..6e02af552db 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/services/dashboard/DashboardServiceResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/services/dashboard/DashboardServiceResource.java @@ -30,6 +30,7 @@ import org.openmetadata.catalog.jdbi3.DashboardServiceRepository; import org.openmetadata.catalog.resources.Collection; import org.openmetadata.catalog.security.CatalogAuthorizer; import org.openmetadata.catalog.security.SecurityUtil; +import org.openmetadata.catalog.type.EntityHistory; import org.openmetadata.catalog.util.RestUtil; import org.openmetadata.catalog.util.RestUtil.PutResponse; import org.openmetadata.catalog.util.ResultList; @@ -53,6 +54,7 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.SecurityContext; import javax.ws.rs.core.UriInfo; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.security.GeneralSecurityException; import java.text.ParseException; import java.util.Date; @@ -78,8 +80,12 @@ public class DashboardServiceResource { } public static class DashboardServiceList extends ResultList { - public DashboardServiceList(List data) { - super(data); + @SuppressWarnings("unused") /* Required for tests */ + public DashboardServiceList() {} + + public DashboardServiceList(List data, String beforeCursor, String afterCursor, int total) + throws GeneralSecurityException, UnsupportedEncodingException { + super(data, beforeCursor, afterCursor, total); } } @@ -106,13 +112,11 @@ public class DashboardServiceResource { throws IOException, GeneralSecurityException, ParseException { RestUtil.validateCursors(before, after); - ResultList list; if (before != null) { // Reverse paging - list = dao.listBefore(uriInfo, null, null, limitParam, before); - } else { // Forward paging or first page - list = dao.listAfter(uriInfo, null, null, limitParam, after); + return dao.listBefore(uriInfo, null, null, limitParam, before); } - return list; + // Forward paging + return dao.listAfter(uriInfo, null, null, limitParam, after); } @GET @@ -147,6 +151,43 @@ public class DashboardServiceResource { return dao.getByName(uriInfo, name, null); } + @GET + @Path("/{id}/versions") + @Operation(summary = "List dashboard service versions", tags = "services", + description = "Get a list of all the versions of a dashboard service identified by `id`", + responses = {@ApiResponse(responseCode = "200", description = "List of dashboard service versions", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = EntityHistory.class))) + }) + public EntityHistory listVersions(@Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter(description = "dashboard service Id", schema = @Schema(type = "string")) + @PathParam("id") String id) + throws IOException, ParseException, GeneralSecurityException { + return dao.listVersions(id); + } + + @GET + @Path("/{id}/versions/{version}") + @Operation(summary = "Get a version of the dashboard service", tags = "services", + description = "Get a version of the dashboard service by given `id`", + responses = { + @ApiResponse(responseCode = "200", description = "dashboard service", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = DashboardService.class))), + @ApiResponse(responseCode = "404", description = "Dashboard service for instance {id} and version " + + "{version} is not found") + }) + public DashboardService getVersion(@Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter(description = "dashboard service Id", schema = @Schema(type = "string")) + @PathParam("id") String id, + @Parameter(description = "dashboard service version number in the form `major`" + + ".`minor`", + schema = @Schema(type = "string", example = "0.1 or 1.1")) + @PathParam("version") String version) throws IOException, ParseException { + return dao.getVersion(id, version); + } @POST @Operation(summary = "Create a dashboard service", tags = "services", description = "Create a new dashboard service.", diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/EntityUtil.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/EntityUtil.java index 128b96c4b56..a431ced2591 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/EntityUtil.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/EntityUtil.java @@ -91,6 +91,9 @@ public final class EntityUtil { public static BiPredicate taskMatch = (task1, task2) -> task1.getName().equals(task2.getName()); + public static BiPredicate stringMatch = (string1, string2) -> + string1.equals(string2); + public static BiPredicate columnMatch = (column1, column2) -> column1.getName().equals(column2.getName()) && column1.getDataType() == column2.getDataType() && diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/EntityResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/EntityResourceTest.java index 3d74e585fb3..8642210dd73 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/EntityResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/EntityResourceTest.java @@ -26,6 +26,7 @@ import org.openmetadata.catalog.resources.events.EventResource.ChangeEventList; import org.openmetadata.catalog.resources.services.DatabaseServiceResourceTest; import org.openmetadata.catalog.resources.services.MessagingServiceResourceTest; import org.openmetadata.catalog.resources.tags.TagResourceTest; +import org.openmetadata.catalog.resources.services.PipelineServiceResourceTest; import org.openmetadata.catalog.resources.teams.TeamResourceTest; import org.openmetadata.catalog.resources.teams.UserResourceTest; import org.openmetadata.catalog.type.ChangeDescription; @@ -70,7 +71,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.openmetadata.catalog.resources.services.PipelineServiceResourceTest.createService; import static org.openmetadata.catalog.util.TestUtils.NON_EXISTENT_ENTITY; import static org.openmetadata.catalog.util.TestUtils.UpdateType; import static org.openmetadata.catalog.util.TestUtils.UpdateType.MINOR_UPDATE; @@ -138,45 +138,48 @@ public abstract class EntityResourceTest extends CatalogApplicationTest { CreateDatabaseService createDatabaseService = new CreateDatabaseService() .withName(DatabaseServiceResourceTest.getName(test, 1)) .withServiceType(DatabaseServiceType.Snowflake).withJdbc(TestUtils.JDBC_INFO); - DatabaseService databaseService = DatabaseServiceResourceTest.createService(createDatabaseService, + DatabaseService databaseService = new DatabaseServiceResourceTest().createEntity(createDatabaseService, adminAuthHeaders()); SNOWFLAKE_REFERENCE = new EntityReference().withName(databaseService.getName()).withId(databaseService.getId()) .withType(Entity.DATABASE_SERVICE); + DatabaseServiceResourceTest databaseServieResourceTest = new DatabaseServiceResourceTest(); createDatabaseService.withName("redshiftDB").withServiceType(DatabaseServiceType.Redshift); - databaseService = DatabaseServiceResourceTest.createService(createDatabaseService, adminAuthHeaders()); + databaseService = databaseServieResourceTest.createEntity(createDatabaseService, adminAuthHeaders()); REDSHIFT_REFERENCE = new DatabaseServiceEntityInterface(databaseService).getEntityReference(); createDatabaseService.withName("bigQueryDB").withServiceType(DatabaseServiceType.BigQuery); - databaseService = DatabaseServiceResourceTest.createService(createDatabaseService, adminAuthHeaders()); + databaseService = databaseServieResourceTest.createEntity(createDatabaseService, adminAuthHeaders()); BIGQUERY_REFERENCE = new DatabaseServiceEntityInterface(databaseService).getEntityReference(); createDatabaseService.withName("mysqlDB").withServiceType(DatabaseServiceType.MySQL); - databaseService = DatabaseServiceResourceTest.createService(createDatabaseService, adminAuthHeaders()); + databaseService = databaseServieResourceTest.createEntity(createDatabaseService, adminAuthHeaders()); MYSQL_REFERENCE = new DatabaseServiceEntityInterface(databaseService).getEntityReference(); // Create Kafka messaging service + MessagingServiceResourceTest messagingServiceResourceTest = new MessagingServiceResourceTest(); CreateMessagingService createMessaging = new CreateMessagingService().withName("kafka") .withServiceType(MessagingServiceType.Kafka).withBrokers(List.of("192.168.1.1:0")); - MessagingService messagingService = MessagingServiceResourceTest.createService(createMessaging, adminAuthHeaders()); + MessagingService messagingService = messagingServiceResourceTest.createEntity(createMessaging, adminAuthHeaders()); KAFKA_REFERENCE = new MessagingServiceEntityInterface(messagingService).getEntityReference(); // Create Pulsar messaging service createMessaging.withName("pulsar").withServiceType(MessagingServiceType.Pulsar) .withBrokers(List.of("192.168.1.1:0")); - messagingService = MessagingServiceResourceTest.createService(createMessaging, adminAuthHeaders()); + messagingService = messagingServiceResourceTest.createEntity(createMessaging, adminAuthHeaders()); PULSAR_REFERENCE = new MessagingServiceEntityInterface(messagingService).getEntityReference(); // Create Airflow pipeline service + PipelineServiceResourceTest pipelineServiceResourceTest = new PipelineServiceResourceTest(); CreatePipelineService createPipeline = new CreatePipelineService().withName("airflow") .withServiceType(PipelineServiceType.Airflow).withPipelineUrl(new URI("http://localhost:0")); - PipelineService pipelineService = createService(createPipeline, adminAuthHeaders()); + PipelineService pipelineService = pipelineServiceResourceTest.createEntity(createPipeline, adminAuthHeaders()); AIRFLOW_REFERENCE = new PipelineServiceEntityInterface(pipelineService).getEntityReference(); // Create Prefect pipeline service createPipeline.withName("prefect").withServiceType(PipelineServiceType.Prefect) .withPipelineUrl(new URI("http://localhost:0")); - pipelineService = createService(createPipeline, adminAuthHeaders()); + pipelineService = pipelineServiceResourceTest.createEntity(createPipeline, adminAuthHeaders()); PREFECT_REFERENCE = new PipelineServiceEntityInterface(pipelineService).getEntityReference(); Tag tag = TagResourceTest.getTag("User.Address", adminAuthHeaders()); @@ -601,7 +604,7 @@ public abstract class EntityResourceTest extends CatalogApplicationTest { return TestUtils.get(target, entityClass, authHeaders); } - protected final T createEntity(Object createRequest, Map authHeaders) + public final T createEntity(Object createRequest, Map authHeaders) throws HttpResponseException { return TestUtils.post(getCollection(), createRequest, entityClass, authHeaders); } diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/charts/ChartResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/charts/ChartResourceTest.java index b51d831cf3a..a28b4679676 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/charts/ChartResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/charts/ChartResourceTest.java @@ -75,12 +75,12 @@ public class ChartResourceTest extends EntityResourceTest { CreateDashboardService createService = new CreateDashboardService().withName("superset") .withServiceType(DashboardServiceType.Superset).withDashboardUrl(new URI("http://localhost:0")); - DashboardService service = DashboardServiceResourceTest.createService(createService, adminAuthHeaders()); + DashboardService service = new DashboardServiceResourceTest().createEntity(createService, adminAuthHeaders()); SUPERSET_REFERENCE = new DashboardServiceEntityInterface(service).getEntityReference(); createService.withName("looker").withServiceType(DashboardServiceType.Looker) .withDashboardUrl(new URI("http://localhost:0")); - service = DashboardServiceResourceTest.createService(createService, adminAuthHeaders()); + service = new DashboardServiceResourceTest().createEntity(createService, adminAuthHeaders()); LOOKER_REFERENCE = new DashboardServiceEntityInterface(service).getEntityReference(); } diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/dashboards/DashboardResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/dashboards/DashboardResourceTest.java index c379390c9a6..e57579dd0fe 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/dashboards/DashboardResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/dashboards/DashboardResourceTest.java @@ -90,14 +90,14 @@ public class DashboardResourceTest extends EntityResourceTest { CreateDashboardService createService = new CreateDashboardService().withName("superset") .withServiceType(DashboardServiceType.Superset).withDashboardUrl(TestUtils.DASHBOARD_URL); - DashboardService service = DashboardServiceResourceTest.createService(createService, adminAuthHeaders()); + DashboardService service = new DashboardServiceResourceTest().createEntity(createService, adminAuthHeaders()); SUPERSET_REFERENCE = new DashboardServiceEntityInterface(service).getEntityReference(); SUPERSET_INVALID_SERVICE_REFERENCE = new EntityReference().withName("invalid_superset_service") .withId(SUPERSET_REFERENCE.getId()) .withType("DashboardService1"); createService.withName("looker").withServiceType(DashboardServiceType.Looker); - service = DashboardServiceResourceTest.createService(createService, adminAuthHeaders()); + service = new DashboardServiceResourceTest().createEntity(createService, adminAuthHeaders()); LOOKER_REFERENCE = new DashboardServiceEntityInterface(service).getEntityReference(); CHART_REFERENCES = new ArrayList<>(); for (int i=0; i < 3; i++) { diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/databases/TableResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/databases/TableResourceTest.java index ad7b3779bba..46f67cc2403 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/databases/TableResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/databases/TableResourceTest.java @@ -95,7 +95,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.openmetadata.catalog.resources.databases.DatabaseResourceTest.createAndCheckDatabase; import static org.openmetadata.catalog.resources.locations.LocationResourceTest.createLocation; import static org.openmetadata.catalog.resources.locations.LocationResourceTest.getLocationName; -import static org.openmetadata.catalog.resources.services.DatabaseServiceResourceTest.createService; import static org.openmetadata.catalog.type.ColumnDataType.ARRAY; import static org.openmetadata.catalog.type.ColumnDataType.BIGINT; import static org.openmetadata.catalog.type.ColumnDataType.BINARY; @@ -1052,7 +1051,7 @@ public class TableResourceTest extends EntityResourceTest { // Add location to the table CreateStorageService createService = new CreateStorageService().withName("s3") .withServiceType(StorageServiceType.S3); - StorageService service = StorageServiceResourceTest.createService(createService, adminAuthHeaders()); + StorageService service = new StorageServiceResourceTest().createEntity(createService, adminAuthHeaders()); EntityReference serviceRef = new EntityReference().withName(service.getName()).withId(service.getId()).withType(Entity.STORAGE_SERVICE); CreateLocation create = new CreateLocation().withName(getLocationName(test)).withService(serviceRef); @@ -1217,7 +1216,8 @@ public class TableResourceTest extends EntityResourceTest
{ * set up in the {@code setup()} method */ public Table createEntity(TestInfo test, int index) throws IOException { - DatabaseService service = createService(DatabaseServiceResourceTest.create(test), adminAuthHeaders()); + DatabaseService service = new DatabaseServiceResourceTest().createEntity(DatabaseServiceResourceTest.create(test), + adminAuthHeaders()); EntityReference serviceRef = new EntityReference().withName(service.getName()).withId(service.getId()).withType(Entity.DATABASE_SERVICE); Database database = createAndCheckDatabase(DatabaseResourceTest.create(test).withService(serviceRef), diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/dbtmodels/DbtModelResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/dbtmodels/DbtModelResourceTest.java index 6e4a7602cc0..9c4adda856f 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/dbtmodels/DbtModelResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/dbtmodels/DbtModelResourceTest.java @@ -75,7 +75,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.openmetadata.catalog.resources.databases.DatabaseResourceTest.createAndCheckDatabase; -import static org.openmetadata.catalog.resources.services.DatabaseServiceResourceTest.createService; import static org.openmetadata.catalog.type.ColumnDataType.ARRAY; import static org.openmetadata.catalog.type.ColumnDataType.BIGINT; import static org.openmetadata.catalog.type.ColumnDataType.BINARY; @@ -117,21 +116,6 @@ public class DbtModelResourceTest extends EntityResourceTest { DATABASE = createAndCheckDatabase(create, adminAuthHeaders()); } - public static DbtModel createDbtModel(TestInfo test, int i) throws IOException { - return new DbtModelResourceTest().createEntity(test, i); - } - - public static DbtModel createDbtModel(CreateDbtModel createDbtModel, Map adminAuthHeaders) - throws HttpResponseException { - return new DbtModelResourceTest().createEntity(createDbtModel, adminAuthHeaders); - } - - public static DbtModel createAndCheckDbtModel(CreateDbtModel createDbtModel, Map adminAuthHeaders) - throws IOException { - return new DbtModelResourceTest().createAndCheckEntity(createDbtModel, adminAuthHeaders); - } - - @Test public void post_DbtModelWithoutName_400_badRequest(TestInfo test) { // Create DbtModel with mandatory name field empty @@ -764,7 +748,8 @@ public class DbtModelResourceTest extends EntityResourceTest { * set up in the {@code setup()} method */ public DbtModel createEntity(TestInfo test, int index) throws IOException { - DatabaseService service = createService(DatabaseServiceResourceTest.create(test), adminAuthHeaders()); + DatabaseService service = new DatabaseServiceResourceTest().createEntity(DatabaseServiceResourceTest.create(test), + adminAuthHeaders()); EntityReference serviceRef = new EntityReference().withName(service.getName()).withId(service.getId()).withType(Entity.DATABASE_SERVICE); Database database = createAndCheckDatabase(DatabaseResourceTest.create(test).withService(serviceRef), diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/locations/LocationResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/locations/LocationResourceTest.java index cad5ed9845c..9b7f6eb0c6c 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/locations/LocationResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/locations/LocationResourceTest.java @@ -103,12 +103,12 @@ public class LocationResourceTest extends CatalogApplicationTest { CreateStorageService createService = new CreateStorageService().withName("s3") .withServiceType(StorageServiceType.S3); - StorageService service = StorageServiceResourceTest.createService(createService, adminAuthHeaders()); + StorageService service = new StorageServiceResourceTest().createEntity(createService, adminAuthHeaders()); AWS_REFERENCE = new EntityReference().withName(service.getName()).withId(service.getId()) .withType(Entity.STORAGE_SERVICE); createService.withName("gs").withServiceType(StorageServiceType.GCS); - service = StorageServiceResourceTest.createService(createService, adminAuthHeaders()); + service = new StorageServiceResourceTest().createEntity(createService, adminAuthHeaders()); GCP_REFERENCE = new EntityReference().withName(service.getName()).withId(service.getId()) .withType(Entity.STORAGE_SERVICE); diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/mlmodels/MlModelResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/mlmodels/MlModelResourceTest.java index bad41f7c59e..fc3efb5be92 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/mlmodels/MlModelResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/mlmodels/MlModelResourceTest.java @@ -132,7 +132,7 @@ public class MlModelResourceTest extends CatalogApplicationTest { CreateDashboardService createService = new CreateDashboardService().withName("superset") .withServiceType(DashboardServiceType.Superset).withDashboardUrl(TestUtils.DASHBOARD_URL); - DashboardService service = DashboardServiceResourceTest.createService(createService, adminAuthHeaders()); + DashboardService service = new DashboardServiceResourceTest().createEntity(createService, adminAuthHeaders()); SUPERSET_REFERENCE = new DashboardServiceEntityInterface(service).getEntityReference(); DASHBOARD = DashboardResourceTest.createDashboard( diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/services/DashboardServiceResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/services/DashboardServiceResourceTest.java index 822674f027b..d3d9814ac8b 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/services/DashboardServiceResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/services/DashboardServiceResourceTest.java @@ -25,11 +25,20 @@ import org.openmetadata.catalog.api.services.CreateDashboardService; import org.openmetadata.catalog.api.services.CreateDashboardService.DashboardServiceType; import org.openmetadata.catalog.entity.services.DashboardService; import org.openmetadata.catalog.exception.CatalogExceptionMessage; +import org.openmetadata.catalog.jdbi3.DashboardServiceRepository.DashboardServiceEntityInterface; +import org.openmetadata.catalog.resources.EntityResourceTest; +import org.openmetadata.catalog.resources.services.dashboard.DashboardServiceResource.DashboardServiceList; +import org.openmetadata.catalog.type.ChangeDescription; +import org.openmetadata.catalog.type.EntityReference; +import org.openmetadata.catalog.type.FieldChange; import org.openmetadata.catalog.type.Schedule; +import org.openmetadata.catalog.util.EntityInterface; +import org.openmetadata.catalog.util.JsonUtils; import org.openmetadata.catalog.util.TestUtils; +import org.openmetadata.catalog.util.TestUtils.UpdateType; import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.Response.Status; +import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.Date; @@ -42,18 +51,24 @@ import static javax.ws.rs.core.Response.Status.FORBIDDEN; import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.OK; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.openmetadata.catalog.util.TestUtils.adminAuthHeaders; import static org.openmetadata.catalog.util.TestUtils.authHeaders; +import static org.openmetadata.catalog.util.TestUtils.getPrincipal; + +public class DashboardServiceResourceTest extends EntityResourceTest { + public DashboardServiceResourceTest() { + super(Entity.DASHBOARD_SERVICE, DashboardService.class, DashboardServiceList.class, "services/dashboardServices", + "", false, false, false); + this.supportsPatch = false; + } -public class DashboardServiceResourceTest extends CatalogApplicationTest { @Test public void post_serviceWithLongName_400_badRequest(TestInfo test) throws URISyntaxException { // Create dashboard with mandatory name field empty CreateDashboardService create = create(test).withName(TestUtils.LONG_ENTITY_NAME); HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[name size must be between 1 and 64]"); } @@ -61,41 +76,41 @@ public class DashboardServiceResourceTest extends CatalogApplicationTest { public void post_withoutRequiredFields_400_badRequest(TestInfo test) { // Create dashboard with mandatory name field null HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - createService(create(test).withName(null), adminAuthHeaders())); + createEntity(create(test).withName(null), adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[name must not be null]"); // Create dashboard with mandatory name field empty exception = assertThrows(HttpResponseException.class, () -> - createService(create(test).withName(""), adminAuthHeaders())); + createEntity(create(test).withName(""), adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[name size must be between 1 and 64]"); // Create dashboard with mandatory serviceType field empty exception = assertThrows(HttpResponseException.class, () -> - createService(create(test).withServiceType(null), adminAuthHeaders())); + createEntity(create(test).withServiceType(null), adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[serviceType must not be null]"); // Create dashboard with mandatory brokers field empty exception = assertThrows(HttpResponseException.class, () -> - createService(create(test).withDashboardUrl(null), adminAuthHeaders())); + createEntity(create(test).withDashboardUrl(null), adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[dashboardUrl must not be null]"); } @Test public void post_serviceAlreadyExists_409(TestInfo test) throws HttpResponseException, URISyntaxException { CreateDashboardService create = create(test); - createService(create, adminAuthHeaders()); + createEntity(create, adminAuthHeaders()); HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, CONFLICT, CatalogExceptionMessage.ENTITY_ALREADY_EXISTS); } @Test - public void post_validService_as_admin_200_ok(TestInfo test) throws HttpResponseException, URISyntaxException { + public void post_validService_as_admin_200_ok(TestInfo test) throws IOException, URISyntaxException { // Create dashboard service with different optional fields Map authHeaders = adminAuthHeaders(); - createAndCheckService(create(test, 1).withDescription(null), authHeaders); - createAndCheckService(create(test, 2).withDescription("description"), authHeaders); - createAndCheckService(create(test, 3).withIngestionSchedule(null), authHeaders); + createAndCheckEntity(create(test, 1).withDescription(null), authHeaders); + createAndCheckEntity(create(test, 2).withDescription("description"), authHeaders); + createAndCheckEntity(create(test, 3).withIngestionSchedule(null), authHeaders); } @Test @@ -104,7 +119,7 @@ public class DashboardServiceResourceTest extends CatalogApplicationTest { Map authHeaders = authHeaders("test@open-metadata.org"); HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - createAndCheckService(create(test, 1).withDescription(null), authHeaders)); + createAndCheckEntity(create(test, 1).withDescription(null), authHeaders)); TestUtils.assertResponse(exception, FORBIDDEN, "Principal: CatalogPrincipal{name='test'} is not admin"); } @@ -118,24 +133,24 @@ public class DashboardServiceResourceTest extends CatalogApplicationTest { // Invalid format create.withIngestionSchedule(schedule.withRepeatFrequency("INVALID")); HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Invalid ingestion repeatFrequency INVALID"); // Duration that contains years, months and seconds are not allowed create.withIngestionSchedule(schedule.withRepeatFrequency("P1Y")); - exception = assertThrows(HttpResponseException.class, () -> createService(create, adminAuthHeaders())); + exception = assertThrows(HttpResponseException.class, () -> createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Ingestion repeatFrequency can only contain Days, Hours, " + "and Minutes - example P{d}DT{h}H{m}M"); create.withIngestionSchedule(schedule.withRepeatFrequency("P1M")); - exception = assertThrows(HttpResponseException.class, () -> createService(create, adminAuthHeaders())); + exception = assertThrows(HttpResponseException.class, () -> createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Ingestion repeatFrequency can only contain Days, Hours, " + "and Minutes - example P{d}DT{h}H{m}M"); create.withIngestionSchedule(schedule.withRepeatFrequency("PT1S")); - exception = assertThrows(HttpResponseException.class, () -> createService(create, adminAuthHeaders())); + exception = assertThrows(HttpResponseException.class, () -> createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Ingestion repeatFrequency can only contain Days, Hours, " + "and Minutes - example P{d}DT{h}H{m}M"); @@ -143,16 +158,16 @@ public class DashboardServiceResourceTest extends CatalogApplicationTest { @Test public void post_validIngestionSchedules_as_admin_200(TestInfo test) - throws HttpResponseException, URISyntaxException { + throws IOException, URISyntaxException { Schedule schedule = new Schedule().withStartDate(new Date()); schedule.withRepeatFrequency("PT60M"); // Repeat every 60M should be valid - createAndCheckService(create(test, 1).withIngestionSchedule(schedule), adminAuthHeaders()); + createAndCheckEntity(create(test, 1).withIngestionSchedule(schedule), adminAuthHeaders()); schedule.withRepeatFrequency("PT1H49M"); - createAndCheckService(create(test, 2).withIngestionSchedule(schedule), adminAuthHeaders()); + createAndCheckEntity(create(test, 2).withIngestionSchedule(schedule), adminAuthHeaders()); schedule.withRepeatFrequency("P1DT1H49M"); - createAndCheckService(create(test, 3).withIngestionSchedule(schedule), adminAuthHeaders()); + createAndCheckEntity(create(test, 3).withIngestionSchedule(schedule), adminAuthHeaders()); } @Test @@ -162,45 +177,53 @@ public class DashboardServiceResourceTest extends CatalogApplicationTest { Schedule schedule = create.getIngestionSchedule(); create.withIngestionSchedule(schedule.withRepeatFrequency("PT1M")); // Repeat every 0 seconds HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponseContains(exception, BAD_REQUEST, "Ingestion repeatFrequency is too short and must be more than 60 minutes"); create.withIngestionSchedule(schedule.withRepeatFrequency("PT59M")); // Repeat every 50 minutes 59 seconds - exception = assertThrows(HttpResponseException.class, () -> createService(create, adminAuthHeaders())); + exception = assertThrows(HttpResponseException.class, () -> createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Ingestion repeatFrequency is too short and must " + "be more than 60 minutes"); } @Test - public void put_updateService_as_admin_2xx(TestInfo test) throws HttpResponseException, URISyntaxException { - DashboardService dbService = createAndCheckService(create(test).withDescription(null).withIngestionSchedule(null), + public void put_updateService_as_admin_2xx(TestInfo test) throws IOException, URISyntaxException { + DashboardService service = createAndCheckEntity(create(test).withDescription(null).withIngestionSchedule(null), adminAuthHeaders()); // Update dashboard description and ingestion service that are null + Schedule schedule = new Schedule().withStartDate(new Date()).withRepeatFrequency("P1D"); CreateDashboardService update = create(test).withDescription("description1") - .withDashboardUrl(new URI("http://localhost:8080")).withUsername("user").withPassword("password"); - updateAndCheckService(update, OK, adminAuthHeaders()); + .withDashboardUrl(new URI("http://localhost:8080")).withUsername("user").withPassword("password") + .withIngestionSchedule(schedule); + + ChangeDescription change = getChangeDescription(service.getVersion()); + change.getFieldsAdded().add(new FieldChange().withName("description").withNewValue("description1")); + change.getFieldsAdded().add(new FieldChange().withName("userName").withNewValue("user")); + change.getFieldsAdded().add(new FieldChange().withName("ingestionSchedule").withNewValue(schedule)); + change.getFieldsUpdated().add(new FieldChange().withName("dashboardUrl").withOldValue("http://192.1.1.1:0") + .withNewValue("http://localhost:8080")); + service = updateAndCheckEntity(update, OK, adminAuthHeaders(), UpdateType.MINOR_UPDATE, change); // Update ingestion schedule - Schedule schedule = new Schedule().withStartDate(new Date()).withRepeatFrequency("P1D"); - update.withIngestionSchedule(schedule); - updateAndCheckService(update, OK, adminAuthHeaders()); - - // Update description and ingestion schedule again - update.withDescription("description1").withIngestionSchedule(schedule.withRepeatFrequency("PT1H")); - updateAndCheckService(update, OK, adminAuthHeaders()); + Schedule schedule1 = new Schedule().withStartDate(new Date()).withRepeatFrequency("PT1H"); + change = getChangeDescription(service.getVersion()); + change.getFieldsUpdated().add(new FieldChange().withName("ingestionSchedule").withOldValue(schedule) + .withNewValue(schedule1)); + update.withIngestionSchedule(schedule1); + updateAndCheckEntity(update, OK, adminAuthHeaders(), UpdateType.MINOR_UPDATE, change); } @Test - public void put_update_as_non_admin_401(TestInfo test) throws HttpResponseException, URISyntaxException { + public void put_update_as_non_admin_401(TestInfo test) throws IOException, URISyntaxException { Map authHeaders = adminAuthHeaders(); - DashboardService dbService = createAndCheckService(create(test).withDescription(null).withIngestionSchedule(null), - authHeaders); + createAndCheckEntity(create(test).withDescription(null).withIngestionSchedule(null), authHeaders); // Update dashboard description and ingestion service that are null HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - updateAndCheckService(create(test), OK, authHeaders("test@open-metadata.org"))); + updateAndCheckEntity(create(test), OK, authHeaders("test@open-metadata.org"), + UpdateType.NO_CHANGE, null)); TestUtils.assertResponse(exception, FORBIDDEN, "Principal: CatalogPrincipal{name='test'} " + "is not admin"); } @@ -208,7 +231,7 @@ public class DashboardServiceResourceTest extends CatalogApplicationTest { @Test public void get_nonExistentService_404_notFound() { HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - getService(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); + getEntity(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); TestUtils.assertResponse(exception, NOT_FOUND, CatalogExceptionMessage.entityNotFound(Entity.DASHBOARD_SERVICE, TestUtils.NON_EXISTENT_ENTITY)); } @@ -221,54 +244,6 @@ public class DashboardServiceResourceTest extends CatalogApplicationTest { "invalidName")); } - public static DashboardService createAndCheckService(CreateDashboardService create, - Map authHeaders) throws HttpResponseException { - String updatedBy = TestUtils.getPrincipal(authHeaders); - DashboardService service = createService(create, authHeaders); - validateService(service, create.getName(), create.getDescription(), create.getIngestionSchedule(), updatedBy); - assertEquals(0.1, service.getVersion()); - - // GET the newly created service and validate - DashboardService getService = getService(service.getId(), authHeaders); - validateService(getService, create.getName(), create.getDescription(), create.getIngestionSchedule(), updatedBy); - - // GET the newly created service by name and validate - getService = getServiceByName(service.getName(), null, authHeaders); - validateService(getService, create.getName(), create.getDescription(), create.getIngestionSchedule(), updatedBy); - return service; - } - - public static DashboardService createService(CreateDashboardService create, - Map authHeaders) throws HttpResponseException { - return TestUtils.post(CatalogApplicationTest.getResource("services/dashboardServices"), - create, DashboardService.class, authHeaders); - } - - private static void validateService(DashboardService service, String expectedName, String expectedDescription, - Schedule expectedIngestion, String expectedUpdatedBy) { - assertNotNull(service.getId()); - assertNotNull(service.getHref()); - assertEquals(expectedName, service.getName()); - assertEquals(expectedDescription, service.getDescription()); - assertEquals(expectedUpdatedBy, service.getUpdatedBy()); - - if (expectedIngestion != null) { - assertEquals(expectedIngestion.getStartDate(), service.getIngestionSchedule().getStartDate()); - assertEquals(expectedIngestion.getRepeatFrequency(), service.getIngestionSchedule().getRepeatFrequency()); - } - } - - public static DashboardService getService(UUID id, Map authHeaders) throws HttpResponseException { - return getService(id, null, authHeaders); - } - - public static DashboardService getService(UUID id, String fields, Map authHeaders) - throws HttpResponseException { - WebTarget target = CatalogApplicationTest.getResource("services/dashboardServices/" + id); - target = fields != null ? target.queryParam("fields", fields) : target; - return TestUtils.get(target, DashboardService.class, authHeaders); - } - public static DashboardService getServiceByName(String name, String fields, Map authHeaders) throws HttpResponseException { WebTarget target = CatalogApplicationTest.getResource("services/dashboardServices/name/" + name); @@ -288,14 +263,14 @@ public class DashboardServiceResourceTest extends CatalogApplicationTest { public void delete_ExistentDashboardService_as_admin_200(TestInfo test) throws HttpResponseException, URISyntaxException { Map authHeaders = adminAuthHeaders(); - DashboardService dashboardService = createService(create(test), authHeaders); + DashboardService dashboardService = createEntity(create(test), authHeaders); deleteService(dashboardService.getId(), dashboardService.getName(), authHeaders); } @Test public void delete_as_user_401(TestInfo test) throws HttpResponseException, URISyntaxException { Map authHeaders = adminAuthHeaders(); - DashboardService dashboardService = createService(create(test), authHeaders); + DashboardService dashboardService = createEntity(create(test), authHeaders); HttpResponseException exception = assertThrows(HttpResponseException.class, () -> deleteService(dashboardService.getId(), dashboardService.getName(), authHeaders("test@open-metadata.org"))); @@ -306,7 +281,7 @@ public class DashboardServiceResourceTest extends CatalogApplicationTest { @Test public void delete_notExistentDashboardService() { HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - getService(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); + getEntity(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); TestUtils.assertResponse(exception, NOT_FOUND, CatalogExceptionMessage.entityNotFound(Entity.DASHBOARD_SERVICE, TestUtils.NON_EXISTENT_ENTITY)); } @@ -315,7 +290,7 @@ public class DashboardServiceResourceTest extends CatalogApplicationTest { TestUtils.delete(CatalogApplicationTest.getResource("services/dashboardServices/" + id), authHeaders); // Ensure deleted service does not exist - HttpResponseException exception = assertThrows(HttpResponseException.class, () -> getService(id, authHeaders)); + HttpResponseException exception = assertThrows(HttpResponseException.class, () -> getEntity(id, authHeaders)); TestUtils.assertResponse(exception, NOT_FOUND, CatalogExceptionMessage.entityNotFound(Entity.DASHBOARD_SERVICE, id)); @@ -338,25 +313,52 @@ public class DashboardServiceResourceTest extends CatalogApplicationTest { .withIngestionSchedule(new Schedule().withStartDate(new Date()).withRepeatFrequency("P1D")); } - public static void updateAndCheckService(CreateDashboardService update, Status status, - Map authHeaders) throws HttpResponseException { - String updatedBy = TestUtils.getPrincipal(authHeaders); - DashboardService service = updateDashboardService(update, status, authHeaders); - validateService(service, service.getName(), update.getDescription(), update.getIngestionSchedule(), updatedBy); - - // GET the newly updated dashboard and validate - DashboardService getService = getService(service.getId(), authHeaders); - validateService(getService, service.getName(), update.getDescription(), update.getIngestionSchedule(), updatedBy); - - // GET the newly updated dashboard by name and validate - getService = getServiceByName(service.getName(), null, authHeaders); - validateService(getService, service.getName(), update.getDescription(), update.getIngestionSchedule(), updatedBy); + @Override + public Object createRequest(TestInfo test, int index, String description, String displayName, EntityReference owner) + throws URISyntaxException { + return create(test, index).withDescription(description).withIngestionSchedule(null); } - public static DashboardService updateDashboardService(CreateDashboardService updated, - Status status, Map authHeaders) + @Override + public void validateCreatedEntity(DashboardService service, Object request, Map authHeaders) throws HttpResponseException { - return TestUtils.put(CatalogApplicationTest.getResource("services/dashboardServices"), updated, - DashboardService.class, status, authHeaders); + CreateDashboardService createRequest = (CreateDashboardService) request; + validateCommonEntityFields(getEntityInterface(service), createRequest.getDescription(), + getPrincipal(authHeaders), null); + assertEquals(createRequest.getName(), service.getName()); + + Schedule expectedIngestion = createRequest.getIngestionSchedule(); + if (expectedIngestion != null) { + assertEquals(expectedIngestion.getStartDate(), service.getIngestionSchedule().getStartDate()); + assertEquals(expectedIngestion.getRepeatFrequency(), service.getIngestionSchedule().getRepeatFrequency()); + } + } + + @Override + public void validateUpdatedEntity(DashboardService service, Object request, Map authHeaders) + throws HttpResponseException { + validateCreatedEntity(service, request, authHeaders); + } + + @Override + public void compareEntities(DashboardService expected, DashboardService updated, Map authHeaders) + throws HttpResponseException { + // PATCH operation is not supported by this entity + } + + @Override + public EntityInterface getEntityInterface(DashboardService entity) { + return new DashboardServiceEntityInterface(entity); + } + + @Override + public void assertFieldChange(String fieldName, Object expected, Object actual) throws IOException { + if (fieldName.equals("ingestionSchedule")) { + Schedule expectedSchedule = (Schedule) expected; + Schedule actualSchedule = JsonUtils.readValue((String) actual, Schedule.class); + assertEquals(expectedSchedule, actualSchedule); + } else { + super.assertCommonFieldChange(fieldName, expected, actual); + } } } diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/services/DatabaseServiceResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/services/DatabaseServiceResourceTest.java index bc4209a903a..8d55cbf9283 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/services/DatabaseServiceResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/services/DatabaseServiceResourceTest.java @@ -28,14 +28,16 @@ import org.openmetadata.catalog.exception.CatalogExceptionMessage; import org.openmetadata.catalog.jdbi3.DatabaseServiceRepository.DatabaseServiceEntityInterface; import org.openmetadata.catalog.resources.EntityResourceTest; import org.openmetadata.catalog.resources.services.database.DatabaseServiceResource.DatabaseServiceList; +import org.openmetadata.catalog.type.ChangeDescription; import org.openmetadata.catalog.type.EntityReference; -import org.openmetadata.catalog.type.JdbcInfo; +import org.openmetadata.catalog.type.FieldChange; import org.openmetadata.catalog.type.Schedule; import org.openmetadata.catalog.util.EntityInterface; +import org.openmetadata.catalog.util.JsonUtils; import org.openmetadata.catalog.util.TestUtils; +import org.openmetadata.catalog.util.TestUtils.UpdateType; import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.Response.Status; import java.io.IOException; import java.net.URISyntaxException; import java.util.Date; @@ -48,10 +50,10 @@ import static javax.ws.rs.core.Response.Status.FORBIDDEN; import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.OK; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.openmetadata.catalog.util.TestUtils.adminAuthHeaders; import static org.openmetadata.catalog.util.TestUtils.authHeaders; +import static org.openmetadata.catalog.util.TestUtils.getPrincipal; public class DatabaseServiceResourceTest extends EntityResourceTest { public DatabaseServiceResourceTest() { @@ -65,7 +67,7 @@ public class DatabaseServiceResourceTest extends EntityResourceTest - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[name size must be between 1 and 64]"); } @@ -74,16 +76,16 @@ public class DatabaseServiceResourceTest extends EntityResourceTest - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[name size must be between 1 and 64]"); } @Test public void post_databaseServiceAlreadyExists_409(TestInfo test) throws HttpResponseException { CreateDatabaseService create = create(test); - createService(create, adminAuthHeaders()); + createEntity(create, adminAuthHeaders()); HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, CONFLICT, CatalogExceptionMessage.ENTITY_ALREADY_EXISTS); } @@ -112,7 +114,7 @@ public class DatabaseServiceResourceTest extends EntityResourceTest - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponseContains(exception, BAD_REQUEST, "jdbc must not be null"); } @@ -125,24 +127,24 @@ public class DatabaseServiceResourceTest extends EntityResourceTest - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Invalid ingestion repeatFrequency INVALID"); // Duration that contains years, months and seconds are not allowed create.withIngestionSchedule(schedule.withRepeatFrequency("P1Y")); - exception = assertThrows(HttpResponseException.class, () -> createService(create, adminAuthHeaders())); + exception = assertThrows(HttpResponseException.class, () -> createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Ingestion repeatFrequency can only contain Days, Hours, " + "and Minutes - example P{d}DT{h}H{m}M"); create.withIngestionSchedule(schedule.withRepeatFrequency("P1M")); - exception = assertThrows(HttpResponseException.class, () -> createService(create, adminAuthHeaders())); + exception = assertThrows(HttpResponseException.class, () -> createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Ingestion repeatFrequency can only contain Days, Hours, " + "and Minutes - example P{d}DT{h}H{m}M"); create.withIngestionSchedule(schedule.withRepeatFrequency("PT1S")); - exception = assertThrows(HttpResponseException.class, () -> createService(create, adminAuthHeaders())); + exception = assertThrows(HttpResponseException.class, () -> createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Ingestion repeatFrequency can only contain Days, Hours, " + "and Minutes - example P{d}DT{h}H{m}M"); @@ -168,30 +170,36 @@ public class DatabaseServiceResourceTest extends EntityResourceTest - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponseContains(exception, BAD_REQUEST, "Ingestion repeatFrequency is too short and must be more than 60 minutes"); create.withIngestionSchedule(schedule.withRepeatFrequency("PT59M")); // Repeat every 50 minutes 59 seconds - exception = assertThrows(HttpResponseException.class, () -> createService(create, adminAuthHeaders())); + exception = assertThrows(HttpResponseException.class, () -> createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Ingestion repeatFrequency is too short and must " + "be more than 60 minutes"); } @Test public void put_updateDatabaseService_as_admin_2xx(TestInfo test) throws IOException { - createAndCheckEntity(create(test).withDescription(null).withIngestionSchedule(null), adminAuthHeaders()); + DatabaseService service = createAndCheckEntity(create(test).withDescription(null).withIngestionSchedule(null), + adminAuthHeaders()); + // Update database description and ingestion service that are null CreateDatabaseService update = create(test).withDescription("description1"); - updateAndCheckService(update, OK, adminAuthHeaders()); - // Update ingestion schedule - Schedule schedule = new Schedule().withStartDate(new Date()).withRepeatFrequency("P1D"); - update.withIngestionSchedule(schedule); - updateAndCheckService(update, OK, adminAuthHeaders()); + Schedule schedule = update.getIngestionSchedule(); + ChangeDescription change = getChangeDescription(service.getVersion()); + change.getFieldsAdded().add(new FieldChange().withName("description").withNewValue("description1")); + change.getFieldsAdded().add(new FieldChange().withName("ingestionSchedule").withNewValue(schedule)); + service = updateAndCheckEntity(update, OK, adminAuthHeaders(), UpdateType.MINOR_UPDATE, change); - // Update description and ingestion schedule again - update.withDescription("description1").withIngestionSchedule(schedule.withRepeatFrequency("PT1H")); - updateAndCheckService(update, OK, adminAuthHeaders()); + // Update ingestion schedule + Schedule schedule1 = new Schedule().withStartDate(new Date()).withRepeatFrequency("PT1H"); + update.withIngestionSchedule(schedule1); + change = getChangeDescription(service.getVersion()); + change.getFieldsUpdated().add(new FieldChange().withName("ingestionSchedule") + .withOldValue(schedule).withNewValue(schedule1)); + updateAndCheckEntity(update, OK, adminAuthHeaders(), UpdateType.MINOR_UPDATE, change); } @Test @@ -201,7 +209,8 @@ public class DatabaseServiceResourceTest extends EntityResourceTest - updateAndCheckService(create(test), OK, authHeaders("test@open-metadata.org"))); + updateAndCheckEntity(create(test), OK, authHeaders("test@open-metadata.org"), + UpdateType.MINOR_UPDATE, null)); TestUtils.assertResponse(exception, FORBIDDEN, "Principal: CatalogPrincipal{name='test'} " + "is not admin"); } @@ -209,7 +218,7 @@ public class DatabaseServiceResourceTest extends EntityResourceTest - getService(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); + getEntity(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); TestUtils.assertResponse(exception, NOT_FOUND, CatalogExceptionMessage.entityNotFound(Entity.DATABASE_SERVICE, TestUtils.NON_EXISTENT_ENTITY)); } @@ -222,40 +231,6 @@ public class DatabaseServiceResourceTest extends EntityResourceTest authHeaders) throws HttpResponseException { - return TestUtils.post(CatalogApplicationTest.getResource("services/databaseServices"), - create, DatabaseService.class, authHeaders); - } - - private static void validateService(DatabaseService service, String expectedName, String expectedDescription, - JdbcInfo expectedJdbc, Schedule expectedIngestion, String expectedUpdatedBy) { - assertNotNull(service.getId()); - assertNotNull(service.getHref()); - assertEquals(expectedName, service.getName()); - assertEquals(expectedDescription, service.getDescription()); - assertEquals(expectedUpdatedBy, service.getUpdatedBy()); - - // Validate jdbc - assertEquals(expectedJdbc, service.getJdbc()); - - if (expectedIngestion != null) { - assertEquals(expectedIngestion.getStartDate(), service.getIngestionSchedule().getStartDate()); - assertEquals(expectedIngestion.getRepeatFrequency(), service.getIngestionSchedule().getRepeatFrequency()); - } - } - - public static DatabaseService getService(UUID id, Map authHeaders) throws HttpResponseException { - return getService(id, null, authHeaders); - } - - public static DatabaseService getService(UUID id, String fields, Map authHeaders) - throws HttpResponseException { - WebTarget target = CatalogApplicationTest.getResource("services/databaseServices/" + id); - target = fields != null ? target.queryParam("fields", fields) : target; - return TestUtils.get(target, DatabaseService.class, authHeaders); - } - public static DatabaseService getServiceByName(String name, String fields, Map authHeaders) throws HttpResponseException { WebTarget target = CatalogApplicationTest.getResource("services/databaseServices/name/" + name); @@ -274,14 +249,14 @@ public class DatabaseServiceResourceTest extends EntityResourceTest authHeaders = adminAuthHeaders(); - DatabaseService databaseService = createService(create(test), authHeaders); + DatabaseService databaseService = createEntity(create(test), authHeaders); deleteService(databaseService.getId(), databaseService.getName(), authHeaders); } @Test public void delete_as_user_401(TestInfo test) throws HttpResponseException { Map authHeaders = adminAuthHeaders(); - DatabaseService databaseService = createService(create(test), authHeaders); + DatabaseService databaseService = createEntity(create(test), authHeaders); HttpResponseException exception = assertThrows(HttpResponseException.class, () -> deleteService(databaseService.getId(), databaseService.getName(), authHeaders("test@open-metadata.org"))); @@ -292,7 +267,7 @@ public class DatabaseServiceResourceTest extends EntityResourceTest - getService(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); + getEntity(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); TestUtils.assertResponse(exception, NOT_FOUND, CatalogExceptionMessage.entityNotFound(Entity.DATABASE_SERVICE, TestUtils.NON_EXISTENT_ENTITY)); } @@ -301,7 +276,7 @@ public class DatabaseServiceResourceTest extends EntityResourceTest getService(id, authHeaders)); + HttpResponseException exception = assertThrows(HttpResponseException.class, () -> getEntity(id, authHeaders)); TestUtils.assertResponse(exception, NOT_FOUND, CatalogExceptionMessage.entityNotFound(Entity.DATABASE_SERVICE, id)); // Ensure deleted service does not exist when getting by name @@ -321,31 +296,6 @@ public class DatabaseServiceResourceTest extends EntityResourceTest authHeaders) throws HttpResponseException { - String updatedBy = TestUtils.getPrincipal(authHeaders); - DatabaseService service = updateDatabaseService(update, status, authHeaders); - validateService(service, service.getName(), update.getDescription(), service.getJdbc(), - update.getIngestionSchedule(), updatedBy); - - // GET the newly updated database and validate - DatabaseService getService = getService(service.getId(), authHeaders); - validateService(getService, service.getName(), update.getDescription(), service.getJdbc(), - update.getIngestionSchedule(), updatedBy); - - // GET the newly updated database by name and validate - getService = getServiceByName(service.getName(), null, authHeaders); - validateService(getService, service.getName(), update.getDescription(), service.getJdbc(), - update.getIngestionSchedule(), updatedBy); - } - - public static DatabaseService updateDatabaseService(CreateDatabaseService updated, - Status status, Map authHeaders) - throws HttpResponseException { - return TestUtils.put(CatalogApplicationTest.getResource("services/databaseServices"), updated, - DatabaseService.class, status, authHeaders); - } - @Override public Object createRequest(TestInfo test, int index, String description, String displayName, EntityReference owner) throws URISyntaxException { @@ -353,21 +303,33 @@ public class DatabaseServiceResourceTest extends EntityResourceTest authHeaders) + public void validateCreatedEntity(DatabaseService service, Object request, Map authHeaders) throws HttpResponseException { + CreateDatabaseService createRequest = (CreateDatabaseService) request; + validateCommonEntityFields(getEntityInterface(service), createRequest.getDescription(), getPrincipal(authHeaders), + null); + assertEquals(createRequest.getName(), service.getName()); + // Validate jdbc + assertEquals(createRequest.getJdbc(), service.getJdbc()); + + Schedule expectedIngestion = createRequest.getIngestionSchedule(); + if (expectedIngestion != null) { + assertEquals(expectedIngestion.getStartDate(), service.getIngestionSchedule().getStartDate()); + assertEquals(expectedIngestion.getRepeatFrequency(), service.getIngestionSchedule().getRepeatFrequency()); + } } @Override - public void validateUpdatedEntity(DatabaseService updatedEntity, Object request, Map authHeaders) + public void validateUpdatedEntity(DatabaseService service, Object request, Map authHeaders) throws HttpResponseException { - + validateCreatedEntity(service, request, authHeaders); } @Override public void compareEntities(DatabaseService expected, DatabaseService updated, Map authHeaders) throws HttpResponseException { - + // PATCH operation is not supported by this entity } @Override @@ -377,6 +339,12 @@ public class DatabaseServiceResourceTest extends EntityResourceTest - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[name size must be between 1 and 64]"); } @@ -86,31 +88,31 @@ public class MessagingServiceResourceTest extends EntityResourceTest - createService(create(test).withName(null), adminAuthHeaders())); + createEntity(create(test).withName(null), adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[name must not be null]"); // Create messaging with mandatory name field empty exception = assertThrows(HttpResponseException.class, () -> - createService(create(test).withName(""), adminAuthHeaders())); + createEntity(create(test).withName(""), adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[name size must be between 1 and 64]"); // Create messaging with mandatory serviceType field empty exception = assertThrows(HttpResponseException.class, () -> - createService(create(test).withServiceType(null), adminAuthHeaders())); + createEntity(create(test).withServiceType(null), adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[serviceType must not be null]"); // Create messaging with mandatory brokers field empty exception = assertThrows(HttpResponseException.class, () -> - createService(create(test).withBrokers(null), adminAuthHeaders())); + createEntity(create(test).withBrokers(null), adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[brokers must not be null]"); } @Test public void post_serviceAlreadyExists_409(TestInfo test) throws HttpResponseException { CreateMessagingService create = create(test); - createService(create, adminAuthHeaders()); + createEntity(create, adminAuthHeaders()); HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, CONFLICT, CatalogExceptionMessage.ENTITY_ALREADY_EXISTS); } @@ -143,24 +145,24 @@ public class MessagingServiceResourceTest extends EntityResourceTest - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Invalid ingestion repeatFrequency INVALID"); // Duration that contains years, months and seconds are not allowed create.withIngestionSchedule(schedule.withRepeatFrequency("P1Y")); - exception = assertThrows(HttpResponseException.class, () -> createService(create, adminAuthHeaders())); + exception = assertThrows(HttpResponseException.class, () -> createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Ingestion repeatFrequency can only contain Days, Hours, " + "and Minutes - example P{d}DT{h}H{m}M"); create.withIngestionSchedule(schedule.withRepeatFrequency("P1M")); - exception = assertThrows(HttpResponseException.class, () -> createService(create, adminAuthHeaders())); + exception = assertThrows(HttpResponseException.class, () -> createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Ingestion repeatFrequency can only contain Days, Hours, " + "and Minutes - example P{d}DT{h}H{m}M"); create.withIngestionSchedule(schedule.withRepeatFrequency("PT1S")); - exception = assertThrows(HttpResponseException.class, () -> createService(create, adminAuthHeaders())); + exception = assertThrows(HttpResponseException.class, () -> createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Ingestion repeatFrequency can only contain Days, Hours, " + "and Minutes - example P{d}DT{h}H{m}M"); @@ -186,50 +188,65 @@ public class MessagingServiceResourceTest extends EntityResourceTest - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponseContains(exception, BAD_REQUEST, "Ingestion repeatFrequency is too short and must be more than 60 minutes"); create.withIngestionSchedule(schedule.withRepeatFrequency("PT59M")); // Repeat every 50 minutes 59 seconds - exception = assertThrows(HttpResponseException.class, () -> createService(create, adminAuthHeaders())); + exception = assertThrows(HttpResponseException.class, () -> createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Ingestion repeatFrequency is too short and must " + "be more than 60 minutes"); } @Test public void put_updateService_as_admin_2xx(TestInfo test) throws IOException, URISyntaxException { - MessagingService dbService = createAndCheckEntity(create(test).withDescription(null).withIngestionSchedule(null) + MessagingService service = createAndCheckEntity(create(test).withDescription(null).withIngestionSchedule(null) .withBrokers(KAFKA_BROKERS).withSchemaRegistry(SCHEMA_REGISTRY_URL), adminAuthHeaders()); // Update messaging description and ingestion service that are null CreateMessagingService update = create(test).withDescription("description1").withIngestionSchedule(null); - updateAndCheckService(update, OK, adminAuthHeaders()); + ChangeDescription change = getChangeDescription(service.getVersion()); + change.getFieldsAdded().add(new FieldChange().withName("description").withNewValue("description1")); + service = updateAndCheckEntity(update, OK, adminAuthHeaders(), UpdateType.MINOR_UPDATE, change); // Update ingestion schedule Schedule schedule = new Schedule().withStartDate(new Date()).withRepeatFrequency("P1D"); + change = getChangeDescription(service.getVersion()); + change.getFieldsAdded().add(new FieldChange().withName("ingestionSchedule").withNewValue(schedule)); update.withIngestionSchedule(schedule); - updateAndCheckService(update, OK, adminAuthHeaders()); + service = updateAndCheckEntity(update, OK, adminAuthHeaders(), UpdateType.MINOR_UPDATE, change); // Update description and ingestion schedule again - update.withDescription("description1").withIngestionSchedule(schedule.withRepeatFrequency("PT1H")); - updateAndCheckService(update, OK, adminAuthHeaders()); + Schedule schedule1 = new Schedule().withStartDate(new Date()).withRepeatFrequency("PT1H"); + update.withIngestionSchedule(schedule1); + change = getChangeDescription(service.getVersion()); + change.getFieldsUpdated().add(new FieldChange().withName("ingestionSchedule") + .withOldValue(schedule).withNewValue(schedule1)); + service = updateAndCheckEntity(update, OK, adminAuthHeaders(), UpdateType.MINOR_UPDATE, change); // update broker list and schema registry - update.withBrokers(List.of("localhost:0")).withSchemaRegistry(new URI("http://localhost:9000")); - updateAndCheckService(update, OK, adminAuthHeaders()); - MessagingService updatedService = getService(dbService.getId(), adminAuthHeaders()); - validateMessagingServiceConfig(updatedService, List.of("localhost:0"), new URI("http://localhost:9000")); + List updatedBrokers = List.of("localhost:0"); + URI updatedSchemaRegistry = new URI("http://localhost:9000"); + update.withBrokers(updatedBrokers).withSchemaRegistry(updatedSchemaRegistry); + + change = getChangeDescription(service.getVersion()); + change.getFieldsDeleted().add(new FieldChange().withName("brokers").withOldValue(KAFKA_BROKERS)); + change.getFieldsAdded().add(new FieldChange().withName("brokers").withNewValue(updatedBrokers)); + change.getFieldsUpdated().add(new FieldChange().withName("schemaRegistry") + .withOldValue(SCHEMA_REGISTRY_URL).withNewValue(updatedSchemaRegistry)); + + updateAndCheckEntity(update, OK, adminAuthHeaders(), UpdateType.MINOR_UPDATE, change); } @Test public void put_update_as_non_admin_401(TestInfo test) throws IOException { Map authHeaders = adminAuthHeaders(); - MessagingService dbService = createAndCheckEntity(create(test).withDescription(null).withIngestionSchedule(null), - authHeaders); + createAndCheckEntity(create(test).withDescription(null).withIngestionSchedule(null), authHeaders); // Update messaging description as non admin and expect exception HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - updateAndCheckService(create(test), OK, authHeaders("test@open-metadata.org"))); + updateAndCheckEntity(create(test), OK, authHeaders("test@open-metadata.org"), + UpdateType.NO_CHANGE, null)); TestUtils.assertResponse(exception, FORBIDDEN, "Principal: CatalogPrincipal{name='test'} " + "is not admin"); } @@ -237,7 +254,7 @@ public class MessagingServiceResourceTest extends EntityResourceTest - getService(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); + getEntity(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); TestUtils.assertResponse(exception, NOT_FOUND, CatalogExceptionMessage.entityNotFound(Entity.MESSAGING_SERVICE, TestUtils.NON_EXISTENT_ENTITY)); } @@ -250,37 +267,6 @@ public class MessagingServiceResourceTest extends EntityResourceTest authHeaders) throws HttpResponseException { - return TestUtils.post(CatalogApplicationTest.getResource("services/messagingServices"), - create, MessagingService.class, authHeaders); - } - - private static void validateService(MessagingService service, String expectedName, String expectedDescription, - Schedule expectedIngestion, String expectedUpdatedBy) { - assertNotNull(service.getId()); - assertNotNull(service.getHref()); - assertEquals(expectedName, service.getName()); - assertEquals(expectedDescription, service.getDescription()); - assertEquals(expectedUpdatedBy, service.getUpdatedBy()); - - if (expectedIngestion != null) { - assertEquals(expectedIngestion.getStartDate(), service.getIngestionSchedule().getStartDate()); - assertEquals(expectedIngestion.getRepeatFrequency(), service.getIngestionSchedule().getRepeatFrequency()); - } - } - - public static MessagingService getService(UUID id, Map authHeaders) throws HttpResponseException { - return getService(id, null, authHeaders); - } - - public static MessagingService getService(UUID id, String fields, Map authHeaders) - throws HttpResponseException { - WebTarget target = CatalogApplicationTest.getResource("services/messagingServices/" + id); - target = fields != null ? target.queryParam("fields", fields) : target; - return TestUtils.get(target, MessagingService.class, authHeaders); - } - public static MessagingService getServiceByName(String name, String fields, Map authHeaders) throws HttpResponseException { WebTarget target = CatalogApplicationTest.getResource("services/messagingServices/name/" + name); @@ -299,14 +285,14 @@ public class MessagingServiceResourceTest extends EntityResourceTest authHeaders = adminAuthHeaders(); - MessagingService messagingService = createService(create(test), authHeaders); + MessagingService messagingService = createEntity(create(test), authHeaders); deleteService(messagingService.getId(), messagingService.getName(), authHeaders); } @Test public void delete_as_user_401(TestInfo test) throws HttpResponseException { Map authHeaders = adminAuthHeaders(); - MessagingService messagingService = createService(create(test), authHeaders); + MessagingService messagingService = createEntity(create(test), authHeaders); HttpResponseException exception = assertThrows(HttpResponseException.class, () -> deleteService(messagingService.getId(), messagingService.getName(), authHeaders("test@open-metadata.org"))); @@ -317,7 +303,7 @@ public class MessagingServiceResourceTest extends EntityResourceTest - getService(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); + getEntity(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); TestUtils.assertResponse(exception, NOT_FOUND, CatalogExceptionMessage.entityNotFound(Entity.MESSAGING_SERVICE, TestUtils.NON_EXISTENT_ENTITY)); } @@ -326,7 +312,7 @@ public class MessagingServiceResourceTest extends EntityResourceTest getService(id, authHeaders)); + HttpResponseException exception = assertThrows(HttpResponseException.class, () -> getEntity(id, authHeaders)); TestUtils.assertResponse(exception, NOT_FOUND, CatalogExceptionMessage.entityNotFound(Entity.MESSAGING_SERVICE, id)); @@ -349,34 +335,6 @@ public class MessagingServiceResourceTest extends EntityResourceTest authHeaders) throws HttpResponseException { - String updatedBy = TestUtils.getPrincipal(authHeaders); - MessagingService service = updateMessagingService(update, status, authHeaders); - validateService(service, update.getName(), update.getDescription(), update.getIngestionSchedule(), updatedBy); - - // GET the newly updated messaging and validate - MessagingService getService = getService(service.getId(), authHeaders); - validateService(getService, update.getName(), update.getDescription(), update.getIngestionSchedule(), updatedBy); - - // GET the newly updated messaging by name and validate - getService = getServiceByName(service.getName(), null, authHeaders); - validateService(getService, update.getName(), update.getDescription(), update.getIngestionSchedule(), updatedBy); - } - - public static MessagingService updateMessagingService(CreateMessagingService updated, - Status status, Map authHeaders) - throws HttpResponseException { - return TestUtils.put(CatalogApplicationTest.getResource("services/messagingServices"), updated, - MessagingService.class, status, authHeaders); - } - - private static void validateMessagingServiceConfig(MessagingService actualService, List expectedBrokers, - URI expectedSchemaRegistry) { - assertTrue(actualService.getBrokers().containsAll(expectedBrokers)); - assertEquals(actualService.getSchemaRegistry(), expectedSchemaRegistry); - } - @Override public Object createRequest(TestInfo test, int index, String description, String displayName, EntityReference owner) throws URISyntaxException { @@ -394,6 +352,8 @@ public class MessagingServiceResourceTest extends EntityResourceTest authHeaders) throws HttpResponseException { + // PATCH operation is not supported by this entity } @Override @@ -414,6 +375,20 @@ public class MessagingServiceResourceTest extends EntityResourceTest expectedBrokers = (List) expected; + List actualBrokers = JsonUtils.readObjects((String) actual, String.class); + assertEquals(expectedBrokers, actualBrokers); + } else if (fieldName.equals("schemaRegistry")) { + URI expectedUri = (URI) expected; + URI actualUri = URI.create((String) actual); + assertEquals(expectedUri, actualUri); + } else { + super.assertCommonFieldChange(fieldName, expected, actual); + } } } diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/services/PipelineServiceResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/services/PipelineServiceResourceTest.java index 4f52f13caed..2cb036b18d6 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/services/PipelineServiceResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/services/PipelineServiceResourceTest.java @@ -28,18 +28,20 @@ import org.openmetadata.catalog.exception.CatalogExceptionMessage; import org.openmetadata.catalog.jdbi3.PipelineServiceRepository.PipelineServiceEntityInterface; import org.openmetadata.catalog.resources.EntityResourceTest; import org.openmetadata.catalog.resources.services.pipeline.PipelineServiceResource.PipelineServiceList; +import org.openmetadata.catalog.type.ChangeDescription; import org.openmetadata.catalog.type.EntityReference; +import org.openmetadata.catalog.type.FieldChange; import org.openmetadata.catalog.type.Schedule; import org.openmetadata.catalog.util.EntityInterface; +import org.openmetadata.catalog.util.JsonUtils; import org.openmetadata.catalog.util.TestUtils; +import org.openmetadata.catalog.util.TestUtils.UpdateType; import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.Response.Status; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.Date; -import java.util.List; import java.util.Map; import java.util.UUID; @@ -49,10 +51,10 @@ import static javax.ws.rs.core.Response.Status.FORBIDDEN; import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.OK; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.openmetadata.catalog.util.TestUtils.adminAuthHeaders; import static org.openmetadata.catalog.util.TestUtils.authHeaders; +import static org.openmetadata.catalog.util.TestUtils.getPrincipal; public class PipelineServiceResourceTest extends EntityResourceTest { @@ -65,50 +67,17 @@ public class PipelineServiceResourceTest extends EntityResourceTest authHeaders) - throws HttpResponseException { - - } - - @Override - public void validateUpdatedEntity(PipelineService updatedEntity, Object request, Map authHeaders) - throws HttpResponseException { - - } - - @Override - public void compareEntities(PipelineService expected, PipelineService updated, Map authHeaders) - throws HttpResponseException { - - } - - @Override - public EntityInterface getEntityInterface(PipelineService entity) { - return new PipelineServiceEntityInterface(entity); - } - - @Override - public void assertFieldChange(String fieldName, Object expected, Object actual) throws IOException { - - } - @Test public void post_serviceWithLongName_400_badRequest(TestInfo test) { // Create pipeline with mandatory name field empty CreatePipelineService create = create(test).withName(TestUtils.LONG_ENTITY_NAME); HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[name size must be between 1 and 64]"); } @@ -116,41 +85,41 @@ public class PipelineServiceResourceTest extends EntityResourceTest - createService(create(test).withName(null), adminAuthHeaders())); + createEntity(create(test).withName(null), adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[name must not be null]"); // Create pipeline with mandatory name field empty exception = assertThrows(HttpResponseException.class, () -> - createService(create(test).withName(""), adminAuthHeaders())); + createEntity(create(test).withName(""), adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[name size must be between 1 and 64]"); // Create pipeline with mandatory serviceType field empty exception = assertThrows(HttpResponseException.class, () -> - createService(create(test).withServiceType(null), adminAuthHeaders())); + createEntity(create(test).withServiceType(null), adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[serviceType must not be null]"); // Create pipeline with mandatory brokers field empty exception = assertThrows(HttpResponseException.class, () -> - createService(create(test).withPipelineUrl(null), adminAuthHeaders())); + createEntity(create(test).withPipelineUrl(null), adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[pipelineUrl must not be null]"); } @Test public void post_serviceAlreadyExists_409(TestInfo test) throws HttpResponseException { CreatePipelineService create = create(test); - createService(create, adminAuthHeaders()); + createEntity(create, adminAuthHeaders()); HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, CONFLICT, CatalogExceptionMessage.ENTITY_ALREADY_EXISTS); } @Test - public void post_validService_as_admin_200_ok(TestInfo test) throws HttpResponseException { + public void post_validService_as_admin_200_ok(TestInfo test) throws IOException { // Create pipeline service with different optional fields Map authHeaders = adminAuthHeaders(); - createAndCheckService(create(test, 1).withDescription(null), authHeaders); - createAndCheckService(create(test, 2).withDescription("description"), authHeaders); - createAndCheckService(create(test, 3).withIngestionSchedule(null), authHeaders); + createAndCheckEntity(create(test, 1).withDescription(null), authHeaders); + createAndCheckEntity(create(test, 2).withDescription("description"), authHeaders); + createAndCheckEntity(create(test, 3).withIngestionSchedule(null), authHeaders); } @Test @@ -159,7 +128,7 @@ public class PipelineServiceResourceTest extends EntityResourceTest authHeaders = authHeaders("test@open-metadata.org"); HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - createAndCheckService(create(test, 1).withDescription(null), authHeaders)); + createAndCheckEntity(create(test, 1).withDescription(null), authHeaders)); TestUtils.assertResponse(exception, FORBIDDEN, "Principal: CatalogPrincipal{name='test'} is not admin"); } @@ -173,40 +142,40 @@ public class PipelineServiceResourceTest extends EntityResourceTest - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Invalid ingestion repeatFrequency INVALID"); // Duration that contains years, months and seconds are not allowed create.withIngestionSchedule(schedule.withRepeatFrequency("P1Y")); - exception = assertThrows(HttpResponseException.class, () -> createService(create, adminAuthHeaders())); + exception = assertThrows(HttpResponseException.class, () -> createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Ingestion repeatFrequency can only contain Days, Hours, " + "and Minutes - example P{d}DT{h}H{m}M"); create.withIngestionSchedule(schedule.withRepeatFrequency("P1M")); - exception = assertThrows(HttpResponseException.class, () -> createService(create, adminAuthHeaders())); + exception = assertThrows(HttpResponseException.class, () -> createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Ingestion repeatFrequency can only contain Days, Hours, " + "and Minutes - example P{d}DT{h}H{m}M"); create.withIngestionSchedule(schedule.withRepeatFrequency("PT1S")); - exception = assertThrows(HttpResponseException.class, () -> createService(create, adminAuthHeaders())); + exception = assertThrows(HttpResponseException.class, () -> createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Ingestion repeatFrequency can only contain Days, Hours, " + "and Minutes - example P{d}DT{h}H{m}M"); } @Test - public void post_validIngestionSchedules_as_admin_200(TestInfo test) throws HttpResponseException { + public void post_validIngestionSchedules_as_admin_200(TestInfo test) throws IOException { Schedule schedule = new Schedule().withStartDate(new Date()); schedule.withRepeatFrequency("PT60M"); // Repeat every 60M should be valid - createAndCheckService(create(test, 1).withIngestionSchedule(schedule), adminAuthHeaders()); + createAndCheckEntity(create(test, 1).withIngestionSchedule(schedule), adminAuthHeaders()); schedule.withRepeatFrequency("PT1H49M"); - createAndCheckService(create(test, 2).withIngestionSchedule(schedule), adminAuthHeaders()); + createAndCheckEntity(create(test, 2).withIngestionSchedule(schedule), adminAuthHeaders()); schedule.withRepeatFrequency("P1DT1H49M"); - createAndCheckService(create(test, 3).withIngestionSchedule(schedule), adminAuthHeaders()); + createAndCheckEntity(create(test, 3).withIngestionSchedule(schedule), adminAuthHeaders()); } @Test @@ -216,51 +185,55 @@ public class PipelineServiceResourceTest extends EntityResourceTest - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponseContains(exception, BAD_REQUEST, "Ingestion repeatFrequency is too short and must be more than 60 minutes"); create.withIngestionSchedule(schedule.withRepeatFrequency("PT59M")); // Repeat every 50 minutes 59 seconds - exception = assertThrows(HttpResponseException.class, () -> createService(create, adminAuthHeaders())); + exception = assertThrows(HttpResponseException.class, () -> createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "Ingestion repeatFrequency is too short and must " + "be more than 60 minutes"); } @Test - public void put_updateService_as_admin_2xx(TestInfo test) throws HttpResponseException, URISyntaxException { - PipelineService dbService = createAndCheckService(create(test).withDescription(null).withIngestionSchedule(null) + public void put_updateService_as_admin_2xx(TestInfo test) throws IOException, URISyntaxException { + PipelineService service = createAndCheckEntity(create(test).withDescription(null).withIngestionSchedule(null) .withPipelineUrl(PIPELINE_SERVICE_URL), adminAuthHeaders()); // Update pipeline description and ingestion service that are null CreatePipelineService update = create(test).withDescription("description1"); - updateAndCheckService(update, OK, adminAuthHeaders()); + Schedule schedule = update.getIngestionSchedule(); + ChangeDescription change = getChangeDescription(service.getVersion()); + change.getFieldsAdded().add(new FieldChange().withName("description").withNewValue("description1")); + change.getFieldsAdded().add(new FieldChange().withName("ingestionSchedule").withNewValue(schedule)); + service = updateAndCheckEntity(update, OK, adminAuthHeaders(), UpdateType.MINOR_UPDATE, change); - // Update ingestion schedule - Schedule schedule = new Schedule().withStartDate(new Date()).withRepeatFrequency("P1D"); - update.withIngestionSchedule(schedule); - updateAndCheckService(update, OK, adminAuthHeaders()); + // Update ingestion schedule again + Schedule schedule1 = new Schedule().withStartDate(new Date()).withRepeatFrequency("PT1H"); + update.withIngestionSchedule(schedule1); + change = getChangeDescription(service.getVersion()); + change.getFieldsUpdated().add(new FieldChange().withName("ingestionSchedule").withOldValue(schedule) + .withNewValue(schedule1)); + service = updateAndCheckEntity(update, OK, adminAuthHeaders(), UpdateType.MINOR_UPDATE, change); - // Update ingestion schedule again - update.withIngestionSchedule(schedule.withRepeatFrequency("PT1H")); - updateAndCheckService(update, OK, adminAuthHeaders()); - - // update broker list and schema registry - update.withPipelineUrl(new URI("http://localhost:9000")); - updateAndCheckService(update, OK, adminAuthHeaders()); - PipelineService updatedService = getService(dbService.getId(), adminAuthHeaders()); - validatePipelineServiceConfig(updatedService, List.of("localhost:0"), new URI("http://localhost:9000")); + // update pipeline Url + URI pipelineUrl = new URI("http://localhost:9000"); + update.withPipelineUrl(pipelineUrl); + change = getChangeDescription(service.getVersion()); + change.getFieldsUpdated().add(new FieldChange().withName("pipelineUrl") + .withOldValue(PIPELINE_SERVICE_URL).withNewValue(pipelineUrl)); + updateAndCheckEntity(update, OK, adminAuthHeaders(), UpdateType.MINOR_UPDATE, change); } @Test - public void put_update_as_non_admin_401(TestInfo test) throws HttpResponseException { + public void put_update_as_non_admin_401(TestInfo test) throws IOException { Map authHeaders = adminAuthHeaders(); - PipelineService pipelineService = createAndCheckService(create(test).withDescription(null) - .withIngestionSchedule(null), - authHeaders); + createAndCheckEntity(create(test).withDescription(null) .withIngestionSchedule(null), authHeaders); // Update pipeline description and ingestion service that are null HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - updateAndCheckService(create(test), OK, authHeaders("test@open-metadata.org"))); + updateAndCheckEntity(create(test), OK, authHeaders("test@open-metadata.org"), + UpdateType.NO_CHANGE, null)); TestUtils.assertResponse(exception, FORBIDDEN, "Principal: CatalogPrincipal{name='test'} " + "is not admin"); } @@ -268,7 +241,7 @@ public class PipelineServiceResourceTest extends EntityResourceTest - getService(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); + getEntity(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); TestUtils.assertResponse(exception, NOT_FOUND, CatalogExceptionMessage.entityNotFound(Entity.PIPELINE_SERVICE, TestUtils.NON_EXISTENT_ENTITY)); } @@ -281,54 +254,6 @@ public class PipelineServiceResourceTest extends EntityResourceTest authHeaders) throws HttpResponseException { - String updatedBy = TestUtils.getPrincipal(authHeaders); - PipelineService service = createService(create, authHeaders); - assertEquals(0.1, service.getVersion()); - validateService(service, create.getName(), create.getDescription(), create.getIngestionSchedule(), updatedBy); - - // GET the newly created service and validate - PipelineService getService = getService(service.getId(), authHeaders); - validateService(getService, create.getName(), create.getDescription(), create.getIngestionSchedule(), updatedBy); - - // GET the newly created service by name and validate - getService = getServiceByName(service.getName(), null, authHeaders); - validateService(getService, create.getName(), create.getDescription(), create.getIngestionSchedule(), updatedBy); - return service; - } - - public static PipelineService createService(CreatePipelineService create, - Map authHeaders) throws HttpResponseException { - return TestUtils.post(CatalogApplicationTest.getResource("services/pipelineServices"), - create, PipelineService.class, authHeaders); - } - - private static void validateService(PipelineService service, String expectedName, String expectedDescription, - Schedule expectedIngestion, String expectedUpdatedBy) { - assertNotNull(service.getId()); - assertNotNull(service.getHref()); - assertEquals(expectedName, service.getName()); - assertEquals(expectedDescription, service.getDescription()); - assertEquals(expectedUpdatedBy, service.getUpdatedBy()); - - if (expectedIngestion != null) { - assertEquals(expectedIngestion.getStartDate(), service.getIngestionSchedule().getStartDate()); - assertEquals(expectedIngestion.getRepeatFrequency(), service.getIngestionSchedule().getRepeatFrequency()); - } - } - - public static PipelineService getService(UUID id, Map authHeaders) throws HttpResponseException { - return getService(id, null, authHeaders); - } - - public static PipelineService getService(UUID id, String fields, Map authHeaders) - throws HttpResponseException { - WebTarget target = CatalogApplicationTest.getResource("services/pipelineServices/" + id); - target = fields != null ? target.queryParam("fields", fields) : target; - return TestUtils.get(target, PipelineService.class, authHeaders); - } - public static PipelineService getServiceByName(String name, String fields, Map authHeaders) throws HttpResponseException { WebTarget target = CatalogApplicationTest.getResource("services/pipelineServices/name/" + name); @@ -347,14 +272,14 @@ public class PipelineServiceResourceTest extends EntityResourceTest authHeaders = adminAuthHeaders(); - PipelineService pipelineService = createService(create(test), authHeaders); + PipelineService pipelineService = createEntity(create(test), authHeaders); deleteService(pipelineService.getId(), pipelineService.getName(), authHeaders); } @Test public void delete_as_user_401(TestInfo test) throws HttpResponseException { Map authHeaders = adminAuthHeaders(); - PipelineService pipelineService = createService(create(test), authHeaders); + PipelineService pipelineService = createEntity(create(test), authHeaders); HttpResponseException exception = assertThrows(HttpResponseException.class, () -> deleteService(pipelineService.getId(), pipelineService.getName(), authHeaders("test@open-metadata.org"))); @@ -365,7 +290,7 @@ public class PipelineServiceResourceTest extends EntityResourceTest - getService(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); + getEntity(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); TestUtils.assertResponse(exception, NOT_FOUND, CatalogExceptionMessage.entityNotFound(Entity.PIPELINE_SERVICE, TestUtils.NON_EXISTENT_ENTITY)); } @@ -374,7 +299,7 @@ public class PipelineServiceResourceTest extends EntityResourceTest getService(id, authHeaders)); + HttpResponseException exception = assertThrows(HttpResponseException.class, () -> getEntity(id, authHeaders)); TestUtils.assertResponse(exception, NOT_FOUND, CatalogExceptionMessage.entityNotFound(Entity.PIPELINE_SERVICE, id)); @@ -398,30 +323,57 @@ public class PipelineServiceResourceTest extends EntityResourceTest authHeaders) throws HttpResponseException { - String updatedBy = TestUtils.getPrincipal(authHeaders); - PipelineService service = updatePipelineService(update, status, authHeaders); - validateService(service, service.getName(), update.getDescription(), update.getIngestionSchedule(), updatedBy); - - // GET the newly updated pipeline and validate - PipelineService getService = getService(service.getId(), authHeaders); - validateService(getService, service.getName(), update.getDescription(), update.getIngestionSchedule(), updatedBy); - - // GET the newly updated pipeline by name and validate - getService = getServiceByName(service.getName(), null, authHeaders); - validateService(getService, service.getName(), update.getDescription(), update.getIngestionSchedule(), updatedBy); + @Override + public Object createRequest(TestInfo test, int index, String description, String displayName, EntityReference owner) + throws URISyntaxException { + return create(test, index).withDescription(description).withIngestionSchedule(null); } - public static PipelineService updatePipelineService(CreatePipelineService updated, - Status status, Map authHeaders) + @Override + public void validateCreatedEntity(PipelineService service, Object request, Map authHeaders) throws HttpResponseException { - return TestUtils.put(CatalogApplicationTest.getResource("services/pipelineServices"), updated, - PipelineService.class, status, authHeaders); + CreatePipelineService createRequest = (CreatePipelineService) request; + validateCommonEntityFields(getEntityInterface(service), createRequest.getDescription(), getPrincipal(authHeaders), + null); + assertEquals(createRequest.getName(), service.getName()); + + Schedule expectedIngestion = createRequest.getIngestionSchedule(); + if (expectedIngestion != null) { + assertEquals(expectedIngestion.getStartDate(), service.getIngestionSchedule().getStartDate()); + assertEquals(expectedIngestion.getRepeatFrequency(), service.getIngestionSchedule().getRepeatFrequency()); + } + assertEquals(createRequest.getPipelineUrl(), service.getPipelineUrl()); } - private static void validatePipelineServiceConfig(PipelineService actualService, List expectedBrokers, - URI expectedUrl) { - assertEquals(actualService.getPipelineUrl(), expectedUrl); + @Override + public void validateUpdatedEntity(PipelineService updatedEntity, Object request, Map authHeaders) + throws HttpResponseException { + validateCreatedEntity(updatedEntity, request, authHeaders); + } + + @Override + public void compareEntities(PipelineService expected, PipelineService updated, Map authHeaders) + throws HttpResponseException { + // PATCH operation is not supported by this entity + } + + @Override + public EntityInterface getEntityInterface(PipelineService entity) { + return new PipelineServiceEntityInterface(entity); + } + + @Override + public void assertFieldChange(String fieldName, Object expected, Object actual) throws IOException { + if (fieldName.equals("ingestionSchedule")) { + Schedule expectedSchedule = (Schedule) expected; + Schedule actualSchedule = JsonUtils.readValue((String) actual, Schedule.class); + assertEquals(expectedSchedule, actualSchedule); + } else if (fieldName.equals("pipelineUrl")) { + URI expectedUri = (URI) expected; + URI actualUri = URI.create((String) actual); + assertEquals(expectedUri, actualUri); + } else { + super.assertCommonFieldChange(fieldName, expected, actual); + } } } diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/services/StorageServiceResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/services/StorageServiceResourceTest.java index 88d5f615d26..7be1c0cdd4e 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/services/StorageServiceResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/services/StorageServiceResourceTest.java @@ -15,9 +15,9 @@ import org.openmetadata.catalog.type.EntityReference; import org.openmetadata.catalog.type.StorageServiceType; import org.openmetadata.catalog.util.EntityInterface; import org.openmetadata.catalog.util.TestUtils; +import org.openmetadata.catalog.util.TestUtils.UpdateType; import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.Response; import java.io.IOException; import java.net.URISyntaxException; import java.util.Map; @@ -29,10 +29,10 @@ import static javax.ws.rs.core.Response.Status.FORBIDDEN; import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.OK; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.openmetadata.catalog.util.TestUtils.adminAuthHeaders; import static org.openmetadata.catalog.util.TestUtils.authHeaders; +import static org.openmetadata.catalog.util.TestUtils.getPrincipal; public class StorageServiceResourceTest extends EntityResourceTest { public StorageServiceResourceTest() { @@ -46,7 +46,7 @@ public class StorageServiceResourceTest extends EntityResourceTest - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[name size must be between 1 and 64]"); } @@ -55,25 +55,25 @@ public class StorageServiceResourceTest extends EntityResourceTest - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, BAD_REQUEST, "[name size must be between 1 and 64]"); } @Test public void post_ServiceAlreadyExists_409(TestInfo test) throws HttpResponseException { CreateStorageService create = create(test); - createService(create, adminAuthHeaders()); + createEntity(create, adminAuthHeaders()); HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - createService(create, adminAuthHeaders())); + createEntity(create, adminAuthHeaders())); TestUtils.assertResponse(exception, CONFLICT, CatalogExceptionMessage.ENTITY_ALREADY_EXISTS); } @Test - public void post_validService_as_admin_200_ok(TestInfo test) throws HttpResponseException { + public void post_validService_as_admin_200_ok(TestInfo test) throws IOException { // Create storage service with different optional fields Map authHeaders = adminAuthHeaders(); - createAndCheckService(create(test, 1).withDescription(null), authHeaders); - createAndCheckService(create(test, 2).withDescription("description"), authHeaders); + createAndCheckEntity(create(test, 1).withDescription(null), authHeaders); + createAndCheckEntity(create(test, 2).withDescription("description"), authHeaders); } @Test @@ -82,33 +82,27 @@ public class StorageServiceResourceTest extends EntityResourceTest authHeaders = authHeaders("test@open-metadata.org"); HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - createAndCheckService(create(test, 1).withDescription(null), authHeaders)); + createAndCheckEntity(create(test, 1).withDescription(null), authHeaders)); TestUtils.assertResponse(exception, FORBIDDEN, "Principal: CatalogPrincipal{name='test'} is not admin"); } @Test - public void put_updateStorageService_as_admin_2xx(TestInfo test) throws HttpResponseException { - StorageService dbService = createAndCheckService(create(test).withDescription(null), adminAuthHeaders()); - String id = dbService.getId().toString(); + public void put_updateStorageService_as_admin_2xx(TestInfo test) throws IOException { + createAndCheckEntity(create(test).withDescription(null), adminAuthHeaders()); - // Update storage description and ingestion service that are null - CreateStorageService update = create(test).withDescription("description1"); - updateAndCheckService(update, OK, adminAuthHeaders()); - - // Update description and ingestion schedule again - update.withDescription("description1"); - updateAndCheckService(update, OK, adminAuthHeaders()); + // TODO add more tests for different fields } @Test - public void put_update_as_non_admin_401(TestInfo test) throws HttpResponseException { + public void put_update_as_non_admin_401(TestInfo test) throws IOException { Map authHeaders = adminAuthHeaders(); - StorageService dbService = createAndCheckService(create(test).withDescription(null), authHeaders); + createAndCheckEntity(create(test).withDescription(null), authHeaders); // Update storage description and ingestion service that are null HttpResponseException exception = assertThrows(HttpResponseException.class, () -> - updateAndCheckService(create(test), OK, authHeaders("test@open-metadata.org"))); + updateAndCheckEntity(create(test), OK, authHeaders("test@open-metadata.org"), + UpdateType.NO_CHANGE, null)); TestUtils.assertResponse(exception, FORBIDDEN, "Principal: CatalogPrincipal{name='test'} " + "is not admin"); } @@ -116,7 +110,7 @@ public class StorageServiceResourceTest extends EntityResourceTest - getService(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); + getEntity(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); TestUtils.assertResponse(exception, NOT_FOUND, CatalogExceptionMessage.entityNotFound(Entity.STORAGE_SERVICE, TestUtils.NON_EXISTENT_ENTITY)); } @@ -132,14 +126,14 @@ public class StorageServiceResourceTest extends EntityResourceTest authHeaders = adminAuthHeaders(); - StorageService storageService = createService(create(test), authHeaders); + StorageService storageService = createEntity(create(test), authHeaders); deleteService(storageService.getId(), storageService.getName(), authHeaders); } @Test public void delete_as_user_401(TestInfo test) throws HttpResponseException { Map authHeaders = adminAuthHeaders(); - StorageService storageService = createService(create(test), authHeaders); + StorageService storageService = createEntity(create(test), authHeaders); HttpResponseException exception = assertThrows(HttpResponseException.class, () -> deleteService(storageService.getId(), storageService.getName(), authHeaders("test@open-metadata.org"))); @@ -150,7 +144,7 @@ public class StorageServiceResourceTest extends EntityResourceTest - getService(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); + getEntity(TestUtils.NON_EXISTENT_ENTITY, adminAuthHeaders())); TestUtils.assertResponse(exception, NOT_FOUND, CatalogExceptionMessage.entityNotFound(Entity.STORAGE_SERVICE, TestUtils.NON_EXISTENT_ENTITY)); } @@ -172,45 +166,6 @@ public class StorageServiceResourceTest extends EntityResourceTest authHeaders) throws HttpResponseException { - return TestUtils.post(CatalogApplicationTest.getResource("services/storageServices"), - create, StorageService.class, authHeaders); - } - - public static StorageService createAndCheckService(CreateStorageService create, - Map authHeaders) throws HttpResponseException { - StorageService service = createService(create, authHeaders); - validateService(service, create.getName(), create.getDescription()); - - // GET the newly created service and validate - StorageService getService = getService(service.getId(), authHeaders); - validateService(getService, create.getName(), create.getDescription()); - - // GET the newly created service by name and validate - getService = getServiceByName(service.getName(), null, authHeaders); - validateService(getService, create.getName(), create.getDescription()); - return service; - } - - private static void validateService(StorageService service, String expectedName, String expectedDescription) { - assertNotNull(service.getId()); - assertNotNull(service.getHref()); - assertEquals(expectedName, service.getName()); - assertEquals(expectedDescription, service.getDescription()); - } - - public static StorageService getService(UUID id, Map authHeaders) throws HttpResponseException { - return getService(id, null, authHeaders); - } - - public static StorageService getService(UUID id, String fields, Map authHeaders) - throws HttpResponseException { - WebTarget target = CatalogApplicationTest.getResource("services/storageServices/" + id); - target = fields != null ? target.queryParam("fields", fields) : target; - return TestUtils.get(target, StorageService.class, authHeaders); - } - public static StorageService getServiceByName(String name, String fields, Map authHeaders) throws HttpResponseException { WebTarget target = CatalogApplicationTest.getResource("services/storageServices/name/" + name); @@ -218,32 +173,11 @@ public class StorageServiceResourceTest extends EntityResourceTest authHeaders) - throws HttpResponseException { - return TestUtils.put(CatalogApplicationTest.getResource("services/storageServices"), updated, - StorageService.class, status, authHeaders); - } - - public static void updateAndCheckService(CreateStorageService update, Response.Status status, - Map authHeaders) throws HttpResponseException { - StorageService service = updateStorageService(update, status, authHeaders); - validateService(service, service.getName(), update.getDescription()); - - // GET the newly updated storage and validate - StorageService getService = getService(service.getId(), authHeaders); - validateService(getService, service.getName(), update.getDescription()); - - // GET the newly updated storage by name and validate - getService = getServiceByName(service.getName(), null, authHeaders); - validateService(getService, service.getName(), update.getDescription()); - } - private void deleteService(UUID id, String name, Map authHeaders) throws HttpResponseException { TestUtils.delete(CatalogApplicationTest.getResource("services/storageServices/" + id), authHeaders); // Ensure deleted service does not exist - HttpResponseException exception = assertThrows(HttpResponseException.class, () -> getService(id, authHeaders)); + HttpResponseException exception = assertThrows(HttpResponseException.class, () -> getEntity(id, authHeaders)); TestUtils.assertResponse(exception, NOT_FOUND, CatalogExceptionMessage.entityNotFound(Entity.STORAGE_SERVICE, id)); @@ -260,18 +194,21 @@ public class StorageServiceResourceTest extends EntityResourceTest authHeaders) throws HttpResponseException { - + public void validateCreatedEntity(StorageService service, Object request, Map authHeaders) throws HttpResponseException { + CreateStorageService createRequest = (CreateStorageService) request; + validateCommonEntityFields(getEntityInterface(service), createRequest.getDescription(), + getPrincipal(authHeaders), null); + assertEquals(createRequest.getName(), service.getName()); } @Override - public void validateUpdatedEntity(StorageService updatedEntity, Object request, Map authHeaders) throws HttpResponseException { - + public void validateUpdatedEntity(StorageService service, Object request, Map authHeaders) throws HttpResponseException { + validateCreatedEntity(service, request, authHeaders); } @Override public void compareEntities(StorageService expected, StorageService updated, Map authHeaders) throws HttpResponseException { - + // PATCH operation is not supported by this entity } @Override @@ -281,6 +218,6 @@ public class StorageServiceResourceTest extends EntityResourceTest