diff --git a/bootstrap/sql/com.mysql.cj.jdbc.Driver/v009__create_db_connection_info.sql b/bootstrap/sql/com.mysql.cj.jdbc.Driver/v009__create_db_connection_info.sql index ae0c05e7f4d..a39a825c2e0 100644 --- a/bootstrap/sql/com.mysql.cj.jdbc.Driver/v009__create_db_connection_info.sql +++ b/bootstrap/sql/com.mysql.cj.jdbc.Driver/v009__create_db_connection_info.sql @@ -50,4 +50,13 @@ CREATE TABLE IF NOT EXISTS objectstore_container_entity ( UNIQUE (fullyQualifiedName) ); - +CREATE TABLE IF NOT EXISTS test_connection_definition ( + id VARCHAR(36) GENERATED ALWAYS AS (json ->> '$.id') STORED NOT NULL, + name VARCHAR(256) GENERATED ALWAYS AS (json ->> '$.name') NOT NULL, + json JSON NOT NULL, + updatedAt BIGINT UNSIGNED GENERATED ALWAYS AS (json ->> '$.updatedAt') NOT NULL, + updatedBy VARCHAR(256) GENERATED ALWAYS AS (json ->> '$.updatedBy') NOT NULL, + deleted BOOLEAN GENERATED ALWAYS AS (json -> '$.deleted'), + PRIMARY KEY (id), + UNIQUE (name) +); diff --git a/bootstrap/sql/org.postgresql.Driver/v009__create_db_connection_info.sql b/bootstrap/sql/org.postgresql.Driver/v009__create_db_connection_info.sql index 491d3272fe1..8e8cb27f8b0 100644 --- a/bootstrap/sql/org.postgresql.Driver/v009__create_db_connection_info.sql +++ b/bootstrap/sql/org.postgresql.Driver/v009__create_db_connection_info.sql @@ -50,3 +50,13 @@ CREATE TABLE IF NOT EXISTS objectstore_container_entity ( PRIMARY KEY (id), UNIQUE (fullyQualifiedName) ); + +CREATE TABLE IF NOT EXISTS test_connection_definition ( + id VARCHAR(36) GENERATED ALWAYS AS (json ->> 'id') STORED NOT NULL, + name VARCHAR(256) GENERATED ALWAYS AS (json ->> 'name') STORED NOT NULL, + json JSONB NOT NULL, + updatedAt BIGINT GENERATED ALWAYS AS ((json ->> 'updatedAt')::bigint) STORED NOT NULL, + updatedBy VARCHAR(256) GENERATED ALWAYS AS (json ->> 'updatedBy') STORED NOT NULL, + deleted BOOLEAN GENERATED ALWAYS AS ((json ->> 'deleted')::boolean) STORED, + UNIQUE (name) +); diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/Entity.java b/openmetadata-service/src/main/java/org/openmetadata/service/Entity.java index ef049a5c7dd..fd993df6e61 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/Entity.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/Entity.java @@ -101,6 +101,7 @@ public final class Entity { public static final String CLASSIFICATION = "classification"; public static final String TYPE = "type"; public static final String TEST_DEFINITION = "testDefinition"; + public static final String TEST_CONNECTION_DEFINITION = "testConnectionDefinition"; public static final String ALERT_ACTION = "alertAction"; public static final String TEST_SUITE = "testSuite"; diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/CollectionDAO.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/CollectionDAO.java index 30d5eaef155..d557c6fbea2 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/CollectionDAO.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/CollectionDAO.java @@ -85,6 +85,7 @@ import org.openmetadata.schema.entity.services.MlModelService; import org.openmetadata.schema.entity.services.ObjectStoreService; import org.openmetadata.schema.entity.services.PipelineService; import org.openmetadata.schema.entity.services.StorageService; +import org.openmetadata.schema.entity.services.connections.TestConnectionDefinition; import org.openmetadata.schema.entity.services.ingestionPipelines.IngestionPipeline; import org.openmetadata.schema.entity.teams.Role; import org.openmetadata.schema.entity.teams.Team; @@ -242,6 +243,9 @@ public interface CollectionDAO { @CreateSqlObject TestDefinitionDAO testDefinitionDAO(); + @CreateSqlObject + TestConnectionDefinitionDAO testConnectionDefinitionDAO(); + @CreateSqlObject AlertActionDAO alertActionDAO(); @@ -368,6 +372,23 @@ public interface CollectionDAO { } } + interface TestConnectionDefinitionDAO extends EntityDAO { + @Override + default String getTableName() { + return "test_connection_definition"; + } + + @Override + default Class getEntityClass() { + return TestConnectionDefinition.class; + } + + @Override + default String getNameColumn() { + return "name"; + } + } + interface StorageServiceDAO extends EntityDAO { @Override default String getTableName() { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TestConnectionDefinitionRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TestConnectionDefinitionRepository.java new file mode 100644 index 00000000000..c2e8235ff6b --- /dev/null +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TestConnectionDefinitionRepository.java @@ -0,0 +1,68 @@ +package org.openmetadata.service.jdbi3; + +import static org.openmetadata.service.Entity.TEST_CONNECTION_DEFINITION; + +import java.io.IOException; +import org.openmetadata.common.utils.CommonUtil; +import org.openmetadata.schema.entity.services.connections.TestConnectionDefinition; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.service.Entity; +import org.openmetadata.service.resources.services.connections.TestConnectionDefinitionResource; +import org.openmetadata.service.util.EntityUtil; + +/* + We won't have any POST/PUT operations on these definitions. + They are created by the server and will be updated, if needed, via migration files. +*/ +public class TestConnectionDefinitionRepository extends EntityRepository { + + private static final String UPDATE_FIELDS = ""; + private static final String PATCH_FIELDS = ""; + + public TestConnectionDefinitionRepository(CollectionDAO dao) { + super( + TestConnectionDefinitionResource.COLLECTION_PATH, + TEST_CONNECTION_DEFINITION, + TestConnectionDefinition.class, + dao.testConnectionDefinitionDAO(), + dao, + PATCH_FIELDS, + UPDATE_FIELDS); + } + + @Override + public TestConnectionDefinition setFields(TestConnectionDefinition entity, EntityUtil.Fields fields) + throws IOException { + return entity.withOwner(fields.contains(Entity.FIELD_OWNER) ? getOwner(entity) : null); + } + + @Override + public void prepare(TestConnectionDefinition entity) throws IOException { + // validate steps + if (CommonUtil.nullOrEmpty(entity.getSteps())) { + throw new IllegalArgumentException("Steps must not be empty"); + } + } + + @Override + public void storeEntity(TestConnectionDefinition entity, boolean update) throws IOException { + EntityReference owner = entity.getOwner(); + // Don't store owner, database, href and tags as JSON. Build it on the fly based on relationships + entity.withOwner(null).withHref(null); + store(entity, update); + + // Restore the relationships + entity.withOwner(owner); + } + + @Override + public void storeRelationships(TestConnectionDefinition entity) throws IOException { + storeOwner(entity, entity.getOwner()); + } + + @Override + public EntityUpdater getUpdater( + TestConnectionDefinition original, TestConnectionDefinition updated, Operation operation) { + return null; + } +} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/dqtests/TestDefinitionResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/dqtests/TestDefinitionResource.java index 6fff96a0789..cfb415c0140 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/dqtests/TestDefinitionResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/dqtests/TestDefinitionResource.java @@ -233,7 +233,6 @@ public class TestDefinitionResource extends EntityResource { + public static final String COLLECTION_PATH = "/v1/services/testConnectionDefinition"; + static final String FIELDS = "owner"; + + @Override + public TestConnectionDefinition addHref(UriInfo uriInfo, TestConnectionDefinition testConnectionDefinition) { + testConnectionDefinition.withHref(RestUtil.getHref(uriInfo, COLLECTION_PATH, testConnectionDefinition.getId())); + Entity.withHref(uriInfo, testConnectionDefinition.getOwner()); + return testConnectionDefinition; + } + + @Inject + public TestConnectionDefinitionResource(CollectionDAO dao, Authorizer authorizer) { + super(TestConnectionDefinition.class, new TestConnectionDefinitionRepository(dao), authorizer); + } + + @Override + public void initialize(OpenMetadataApplicationConfig config) throws IOException { + List testConnectionDefinitions = + dao.getEntitiesFromSeedData(".*json/data/testConnections/.*\\.json$"); + for (TestConnectionDefinition testConnectionDefinition : testConnectionDefinitions) { + dao.initializeEntity(testConnectionDefinition); + } + } + + public static class TestConnectionDefinitionList extends ResultList { + @SuppressWarnings("unused") + public TestConnectionDefinitionList() { + // Empty constructor needed for deserialization + } + } + + @GET + @Operation( + operationId = "listTestConnectionDefinitions", + summary = "List test connection definitions", + tags = "testConnectionDefinitions", + description = + "Get a list of test connection definitions. Use cursor-based pagination to limit the number " + + "entries in the list using `limit` and `before` or `after` query params.", + responses = { + @ApiResponse( + responseCode = "200", + description = "List of test connection definitions", + content = + @Content( + mediaType = "application/json", + schema = + @Schema(implementation = TestConnectionDefinitionResource.TestConnectionDefinitionList.class))) + }) + public ResultList list( + @Context UriInfo uriInfo, + @Context SecurityContext securityContext, + @Parameter( + description = "Fields requested in the returned resource", + schema = @Schema(type = "string", example = FIELDS)) + @QueryParam("fields") + String fieldsParam, + @Parameter( + description = "Limit the number test connection definitions returned. (1 to 1000000, default = " + "10)") + @DefaultValue("10") + @QueryParam("limit") + @Min(0) + @Max(1000000) + int limitParam, + @Parameter( + description = "Returns list of test connection definitions before this cursor", + schema = @Schema(type = "string")) + @QueryParam("before") + String before, + @Parameter( + description = "Returns list of test connection definitions after this cursor", + schema = @Schema(type = "string")) + @QueryParam("after") + String after, + @Parameter( + description = "Include all, deleted, or non-deleted entities.", + schema = @Schema(implementation = Include.class)) + @QueryParam("include") + @DefaultValue("non-deleted") + Include include) + throws IOException { + ListFilter filter = new ListFilter(include); + + return super.listInternal(uriInfo, securityContext, fieldsParam, filter, limitParam, before, after); + } + + @GET + @Path("/{id}") + @Operation( + summary = "Get a test connection definition by Id", + tags = "testConnectionDefinitions", + description = "Get a Test Connection Definition by `Id`.", + responses = { + @ApiResponse( + responseCode = "200", + description = "The Test Connection definition", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = TestConnectionDefinition.class))), + @ApiResponse(responseCode = "404", description = "Test Connection Definition for instance {id} is not found") + }) + public TestConnectionDefinition get( + @Context UriInfo uriInfo, + @Parameter(description = "Id of the test connection definition", schema = @Schema(type = "UUID")) @PathParam("id") + UUID id, + @Context SecurityContext securityContext, + @Parameter( + description = "Fields requested in the returned resource", + schema = @Schema(type = "string", example = FIELDS)) + @QueryParam("fields") + String fieldsParam, + @Parameter( + description = "Include all, deleted, or non-deleted entities.", + schema = @Schema(implementation = Include.class)) + @QueryParam("include") + @DefaultValue("non-deleted") + Include include) + throws IOException { + return getInternal(uriInfo, securityContext, id, fieldsParam, include); + } + + @GET + @Path("/name/{name}") + @Operation( + operationId = "getTestConnectionDefinitionByName", + summary = "Get a test connection definition by name", + tags = "testConnectionDefinitions", + description = "Get a test connection definition by `name`.", + responses = { + @ApiResponse( + responseCode = "200", + description = "The test connection definition", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = TestConnectionDefinition.class))), + @ApiResponse(responseCode = "404", description = "Test Connection Definition for instance {name} is not found") + }) + public TestConnectionDefinition getByName( + @Context UriInfo uriInfo, + @Parameter(description = "Name of the test definition", schema = @Schema(type = "string")) @PathParam("name") + String name, + @Context SecurityContext securityContext, + @Parameter( + description = "Fields requested in the returned resource", + schema = @Schema(type = "string", example = FIELDS)) + @QueryParam("fields") + String fieldsParam, + @Parameter( + description = "Include all, deleted, or non-deleted entities.", + schema = @Schema(implementation = Include.class)) + @QueryParam("include") + @DefaultValue("non-deleted") + Include include) + throws IOException { + return getByNameInternal(uriInfo, securityContext, name, fieldsParam, include); + } +} diff --git a/openmetadata-service/src/main/resources/json/data/ResourceDescriptors.json b/openmetadata-service/src/main/resources/json/data/ResourceDescriptors.json index 489da38e0e9..a71f2247fe6 100644 --- a/openmetadata-service/src/main/resources/json/data/ResourceDescriptors.json +++ b/openmetadata-service/src/main/resources/json/data/ResourceDescriptors.json @@ -453,6 +453,14 @@ "ViewAll" ] }, + { + "name" : "testConnectionDefinition", + "operations" : [ + "Create", + "Delete", + "ViewAll" + ] + }, { "name" : "type", "operations" : [ diff --git a/openmetadata-service/src/main/resources/json/data/testConnections/dashboard/tableau.json b/openmetadata-service/src/main/resources/json/data/testConnections/dashboard/tableau.json new file mode 100644 index 00000000000..1657f4c8558 --- /dev/null +++ b/openmetadata-service/src/main/resources/json/data/testConnections/dashboard/tableau.json @@ -0,0 +1,24 @@ +{ + "name": "Tableau", + "fullyQualifiedName": "Tableau", + "displayName": "Tableau Test Connection", + "description": "This Test Connection validates the access against the server and basic metadata extraction of workbooks and views.", + "steps": [ + { + "name": "ServerInfo", + "description": "Validate that the API can properly reach the server", + "mandatory": true + }, + { + "name": "GetWorkbooks", + "description": "List all the workbooks available to the user. We will ingest Workbooks as Dashboards.", + "mandatory": true + }, + { + "name": "GetViews", + "description": "List the Views (charts) from a given Workbook.", + "mandatory": false + } + ] +} + diff --git a/openmetadata-service/src/main/resources/json/data/testConnections/database/mysql.json b/openmetadata-service/src/main/resources/json/data/testConnections/database/mysql.json new file mode 100644 index 00000000000..a1a260409ac --- /dev/null +++ b/openmetadata-service/src/main/resources/json/data/testConnections/database/mysql.json @@ -0,0 +1,24 @@ +{ + "name": "Mysql", + "fullyQualifiedName": "Mysql", + "displayName": "Mysql Test Connection", + "description": "This Test Connection validates the access against the database and basic metadata extraction of schemas and tables.", + "steps": [ + { + "name": "GetSchemas", + "description": "List all the schemas available to the user.", + "mandatory": true + }, + { + "name": "GetTables", + "description": "From a given schema, list the tables belonging to that schema. If no schema is specified, we'll list the tables of a random schema.", + "mandatory": true + }, + { + "name": "GetViews", + "description": "From a given schema, list the views belonging to that schema. If no schema is specified, we'll list the tables of a random schema.", + "mandatory": false + } + ] +} + diff --git a/openmetadata-service/src/main/resources/json/data/testConnections/database/redshift.json b/openmetadata-service/src/main/resources/json/data/testConnections/database/redshift.json new file mode 100644 index 00000000000..9bea4cd59ff --- /dev/null +++ b/openmetadata-service/src/main/resources/json/data/testConnections/database/redshift.json @@ -0,0 +1,39 @@ +{ + "name": "Redshift", + "fullyQualifiedName": "Redshift", + "displayName": "Redshift Test Connection", + "description": "This Test Connection validates the access against the database and basic metadata extraction of schemas and tables.", + "steps": [ + { + "name": "GetDatabases", + "description": "List all the available databases to the user. If all databases option is selected, we will try to go beyond the configured database.", + "mandatory": true + }, + { + "name": "GetSchemas", + "description": "List all the possible schemas from the configured database.", + "mandatory": true + }, + { + "name": "GetTables", + "description": "From a given schema, list the tables belonging to that schema. If no schema is specified, we'll list the tables of a random schema.", + "mandatory": true + }, + { + "name": "GetViews", + "description": "From a given schema, list the views belonging to that schema. If no schema is specified, we'll list the views of a random schema.", + "mandatory": false + }, + { + "name": "GetStlQueryText", + "description": "Check that we can properly access the records in stl_querytext. This is required for lineage and usage workflows.", + "mandatory": false + }, + { + "name": "GetStlQuery", + "description": "Check that we can properly access the records in stl_query. This is required for lineage and usage workflows.", + "mandatory": false + } + ] +} + diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/resources/services/connections/TestConnectionDefinitionResourceTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/resources/services/connections/TestConnectionDefinitionResourceTest.java new file mode 100644 index 00000000000..d231f4fe315 --- /dev/null +++ b/openmetadata-service/src/test/java/org/openmetadata/service/resources/services/connections/TestConnectionDefinitionResourceTest.java @@ -0,0 +1,56 @@ +package org.openmetadata.service.resources.services.connections; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS; + +import java.util.UUID; +import javax.ws.rs.client.WebTarget; +import org.apache.http.client.HttpResponseException; +import org.junit.jupiter.api.Test; +import org.openmetadata.schema.entity.services.connections.TestConnectionDefinition; +import org.openmetadata.service.OpenMetadataApplicationTest; +import org.openmetadata.service.util.ResultList; +import org.openmetadata.service.util.TestUtils; + +/* + This Entity only supports GET, LIST, so we'll validate these endpoints. +*/ +public class TestConnectionDefinitionResourceTest extends OpenMetadataApplicationTest { + + private static final String TEST_CONNECTION_NAME = "Mysql"; + private static final String COLLECTION = "services/testConnectionDefinition"; + + @Test + public void test_get_test_connection_definition() throws HttpResponseException { + WebTarget target = getResourceByName(TEST_CONNECTION_NAME); + TestConnectionDefinition mysqlTest = TestUtils.get(target, TestConnectionDefinition.class, ADMIN_AUTH_HEADERS); + assertEquals(mysqlTest.getName(), "Mysql"); + assertEquals(mysqlTest.getSteps().size(), 3); + + WebTarget idTarget = getResourceById(mysqlTest.getId()); + TestConnectionDefinition mysqlTestById = + TestUtils.get(idTarget, TestConnectionDefinition.class, ADMIN_AUTH_HEADERS); + assertEquals(mysqlTestById.getName(), "Mysql"); + assertEquals(mysqlTestById.getSteps().size(), 3); + } + + @Test + public void test_list_test_connection_definition() throws HttpResponseException { + WebTarget target = listResource(); + ResultList mysqlTest = TestUtils.get(target, ResultList.class, ADMIN_AUTH_HEADERS); + // Update this number after adding new TestConnectionDefinition to the server + assertEquals(mysqlTest.getData().size(), 3); + } + + protected final WebTarget getResourceByName(String name) { + return getResource(COLLECTION).path("/name/" + name); + } + + protected final WebTarget getResourceById(UUID id) { + return getResource(COLLECTION).path("/" + id.toString()); + } + + protected final WebTarget listResource() { + return getResource(COLLECTION).path("/"); + } +} diff --git a/openmetadata-spec/src/main/resources/json/schema/api/services/ingestionPipelines/testServiceConnection.json b/openmetadata-spec/src/main/resources/json/schema/api/services/ingestionPipelines/testServiceConnection.json index 58d37264f93..360ee03a387 100644 --- a/openmetadata-spec/src/main/resources/json/schema/api/services/ingestionPipelines/testServiceConnection.json +++ b/openmetadata-spec/src/main/resources/json/schema/api/services/ingestionPipelines/testServiceConnection.json @@ -44,6 +44,9 @@ "secretsManagerProvider": { "$ref": "../../../security/secrets/secretsManagerProvider.json", "default": "noop" + }, + "serviceName": { + "$ref": "../../../entity/type.json#/definitions/entityName" } }, "additionalProperties": false diff --git a/openmetadata-spec/src/main/resources/json/schema/entity/services/connections/testConnectionDefinition.json b/openmetadata-spec/src/main/resources/json/schema/entity/services/connections/testConnectionDefinition.json new file mode 100644 index 00000000000..e2049ad52b2 --- /dev/null +++ b/openmetadata-spec/src/main/resources/json/schema/entity/services/connections/testConnectionDefinition.json @@ -0,0 +1,94 @@ +{ + "$id": "https://open-metadata.org/schema/entity/services/connections/testConnectionDefinition.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "TestConnectionDefinition", + "description": "TestConnection is the definition that will encapsulate the steps required to test a connection to a specific service.", + "type": "object", + "javaType": "org.openmetadata.schema.entity.services.connections.TestConnectionDefinition", + "javaInterfaces": ["org.openmetadata.schema.EntityInterface"], + "definitions": { + "testConnectionStep": { + "description": "Function that tests one specific element of the service. E.g., listing schemas, lineage, or tags.", + "type": "object", + "javaType": "org.openmetadata.schema.entity.services.connections.TestConnectionStep", + "properties": { + "name": { + "description": "Name of the step being tested", + "type": "string" + }, + "description": { + "description": "What is the goal of the step", + "type": "string" + }, + "mandatory": { + "description": "Is this step mandatory to be passed?", + "type": "boolean", + "default": true + } + }, + "additionalProperties": false, + "required": ["name", "mandatory", "description"] + } + }, + "properties": { + "id": { + "description": "Unique identifier of this test case definition instance.", + "$ref": "../../../type/basic.json#/definitions/uuid" + }, + "name": { + "description": "Name of the Test Connection Definition. It should be the `type` of the service being tested, e.g., Mysql, or Snowflake.", + "$ref": "../../../type/basic.json#/definitions/entityName" + }, + "displayName": { + "description": "Display Name that identifies this test definition.", + "type": "string" + }, + "description": { + "description": "Description of the test connection def.", + "$ref": "../../../type/basic.json#/definitions/markdown" + }, + "fullyQualifiedName": { + "description": "FullyQualifiedName same as `name`.", + "$ref": "../../../type/basic.json#/definitions/fullyQualifiedEntityName" + }, + "steps": { + "description": "Steps to test the connection. Order matters.", + "type": "array", + "items": { + "$ref": "#/definitions/testConnectionStep" + } + }, + "owner": { + "description": "Owner of this TestConnection definition.", + "$ref": "../../../type/entityReference.json", + "default": null + }, + "version": { + "description": "Metadata version of the entity.", + "$ref": "../../../type/entityHistory.json#/definitions/entityVersion" + }, + "updatedAt": { + "description": "Last update time corresponding to the new version of the entity in Unix epoch time milliseconds.", + "$ref": "../../../type/basic.json#/definitions/timestamp" + }, + "updatedBy": { + "description": "User who made the update.", + "type": "string" + }, + "href": { + "description": "Link to the resource corresponding to this entity.", + "$ref": "../../../type/basic.json#/definitions/href" + }, + "changeDescription": { + "description": "Change that lead to this version of the entity.", + "$ref": "../../../type/entityHistory.json#/definitions/changeDescription" + }, + "deleted": { + "description": "When `true` indicates the entity has been soft deleted.", + "type": "boolean", + "default": false + } + }, + "additionalProperties": false, + "required": ["name", "steps"] +} \ No newline at end of file diff --git a/openmetadata-spec/src/main/resources/json/schema/entity/services/connections/testConnectionResult.json b/openmetadata-spec/src/main/resources/json/schema/entity/services/connections/testConnectionResult.json new file mode 100644 index 00000000000..524adb8bf08 --- /dev/null +++ b/openmetadata-spec/src/main/resources/json/schema/entity/services/connections/testConnectionResult.json @@ -0,0 +1,61 @@ +{ + "$id": "https://open-metadata.org/schema/entity/services/connections/testConnectionResult.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "TestConnectionResult", + "description": "TestConnectionResult is the definition that will encapsulate result of running the test connection steps.", + "type": "object", + "javaType": "org.openmetadata.schema.entity.services.connections.TestConnectionResult", + "definitions": { + "testConnectionStepResult": { + "description": "Function that tests one specific element of the service. E.g., listing schemas, lineage, or tags.", + "type": "object", + "javaType": "org.openmetadata.schema.entity.services.connections.TestConnectionStep", + "properties": { + "name": { + "description": "Name of the step being tested", + "type": "string" + }, + "mandatory": { + "description": "Is this step mandatory to be passed?", + "type": "boolean", + "default": true + }, + "passed": { + "description": "Did the step pass successfully?", + "type": "boolean" + }, + "message": { + "description": "Results or exceptions to be shared after running the test.", + "type": "string", + "default": null + } + }, + "additionalProperties": false, + "required": ["name", "mandatory", "passed"] + }, + "statusType": { + "description": "Enum defining possible Test Connection Result status", + "type": "string", + "enum": ["Successful", "Failed", "Running"] + } + }, + "properties": { + "lastUpdatedAt": { + "description": "Last time that the test connection was executed", + "$ref": "../../../type/basic.json#/definitions/timestamp" + }, + "status": { + "description": "Test Connection Result computation status.", + "$ref": "#/definitions/statusType" + }, + "steps": { + "description": "Steps to test the connection. Order matters.", + "type": "array", + "items": { + "$ref": "#/definitions/testConnectionStepResult" + } + } + }, + "additionalProperties": false, + "required": ["steps", "status"] +} \ No newline at end of file diff --git a/openmetadata-spec/src/main/resources/json/schema/entity/services/dashboardService.json b/openmetadata-spec/src/main/resources/json/schema/entity/services/dashboardService.json index 44af3324da6..80a05962232 100644 --- a/openmetadata-spec/src/main/resources/json/schema/entity/services/dashboardService.json +++ b/openmetadata-spec/src/main/resources/json/schema/entity/services/dashboardService.json @@ -138,6 +138,10 @@ "description": "References to pipelines deployed for this dashboard service.", "$ref": "../../type/entityReference.json#/definitions/entityReferenceList" }, + "testConnectionResult": { + "description": "Last test connection results for this service", + "$ref": "connections/testConnectionResult.json" + }, "tags": { "description": "Tags for this Dashboard Service.", "type": "array", diff --git a/openmetadata-spec/src/main/resources/json/schema/entity/services/databaseService.json b/openmetadata-spec/src/main/resources/json/schema/entity/services/databaseService.json index 6112eb4e3f5..6e6a456dd5f 100644 --- a/openmetadata-spec/src/main/resources/json/schema/entity/services/databaseService.json +++ b/openmetadata-spec/src/main/resources/json/schema/entity/services/databaseService.json @@ -271,6 +271,10 @@ "description": "References to pipelines deployed for this database service to extract metadata, usage, lineage etc..", "$ref": "../../type/entityReference.json#/definitions/entityReferenceList" }, + "testConnectionResult": { + "description": "Last test connection results for this service", + "$ref": "connections/testConnectionResult.json" + }, "tags": { "description": "Tags for this Database Service.", "type": "array", diff --git a/openmetadata-spec/src/main/resources/json/schema/entity/services/messagingService.json b/openmetadata-spec/src/main/resources/json/schema/entity/services/messagingService.json index 39cb2ff0437..7c9b7a55540 100644 --- a/openmetadata-spec/src/main/resources/json/schema/entity/services/messagingService.json +++ b/openmetadata-spec/src/main/resources/json/schema/entity/services/messagingService.json @@ -105,6 +105,10 @@ "description": "References to pipelines deployed for this messaging service to extract topic configs and schemas.", "$ref": "../../type/entityReference.json#/definitions/entityReferenceList" }, + "testConnectionResult": { + "description": "Last test connection results for this service", + "$ref": "connections/testConnectionResult.json" + }, "tags": { "description": "Tags for this Message Service.", "type": "array", diff --git a/openmetadata-spec/src/main/resources/json/schema/entity/services/metadataService.json b/openmetadata-spec/src/main/resources/json/schema/entity/services/metadataService.json index 9b2269ca12d..7aed9d90bd7 100644 --- a/openmetadata-spec/src/main/resources/json/schema/entity/services/metadataService.json +++ b/openmetadata-spec/src/main/resources/json/schema/entity/services/metadataService.json @@ -103,6 +103,10 @@ "description": "User who made the update.", "type": "string" }, + "testConnectionResult": { + "description": "Last test connection results for this service", + "$ref": "connections/testConnectionResult.json" + }, "tags": { "description": "Tags for this Metadata Service.", "type": "array", diff --git a/openmetadata-spec/src/main/resources/json/schema/entity/services/mlmodelService.json b/openmetadata-spec/src/main/resources/json/schema/entity/services/mlmodelService.json index 2563a24a526..f33996c1ce0 100644 --- a/openmetadata-spec/src/main/resources/json/schema/entity/services/mlmodelService.json +++ b/openmetadata-spec/src/main/resources/json/schema/entity/services/mlmodelService.json @@ -103,6 +103,10 @@ "connection": { "$ref": "#/definitions/mlModelConnection" }, + "testConnectionResult": { + "description": "Last test connection results for this service", + "$ref": "connections/testConnectionResult.json" + }, "tags": { "description": "Tags for this MlModel Service.", "type": "array", diff --git a/openmetadata-spec/src/main/resources/json/schema/entity/services/objectstoreService.json b/openmetadata-spec/src/main/resources/json/schema/entity/services/objectstoreService.json index 7ebe96c3b14..67d861f32c8 100644 --- a/openmetadata-spec/src/main/resources/json/schema/entity/services/objectstoreService.json +++ b/openmetadata-spec/src/main/resources/json/schema/entity/services/objectstoreService.json @@ -91,6 +91,10 @@ "description": "References to pipelines deployed for this object store service to extract metadata, usage, lineage etc..", "$ref": "../../type/entityReference.json#/definitions/entityReferenceList" }, + "testConnectionResult": { + "description": "Last test connection results for this service", + "$ref": "connections/testConnectionResult.json" + }, "tags": { "description": "Tags for this Object Store Service.", "type": "array", diff --git a/openmetadata-spec/src/main/resources/json/schema/entity/services/pipelineService.json b/openmetadata-spec/src/main/resources/json/schema/entity/services/pipelineService.json index 86b2ceb8bff..090524fa9da 100644 --- a/openmetadata-spec/src/main/resources/json/schema/entity/services/pipelineService.json +++ b/openmetadata-spec/src/main/resources/json/schema/entity/services/pipelineService.json @@ -138,6 +138,10 @@ "description": "User who made the update.", "type": "string" }, + "testConnectionResult": { + "description": "Last test connection results for this service", + "$ref": "connections/testConnectionResult.json" + }, "tags": { "description": "Tags for this Pipeline Service.", "type": "array",