diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 362cf24119..5de813901d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ log4j = "2.24.0" wiremock = "3.9.1" jnanoid = "2.0.0" numaflow = "0.8.0" -awssdk = "2.28.8" +awssdk = "2.28.9" gcs = "26.47.0" system-stubs = "2.1.6" fastcsv = "3.3.1" @@ -19,7 +19,7 @@ simplejavamail = "8.11.3" swagger = "2.1.22" jsonpath = "2.9.0" commons-compress = "1.27.1" -sqlite = "3.46.1.1" +sqlite = "3.46.1.2" jakarta-mail = "2.1.3" angus-mail = "2.0.3" pkl = "0.26.3" diff --git a/integration-tests/src/test/java/com/atlan/java/sdk/SQLAssetTest.java b/integration-tests/src/test/java/com/atlan/java/sdk/SQLAssetTest.java index 9e8deb4b42..e809731be3 100644 --- a/integration-tests/src/test/java/com/atlan/java/sdk/SQLAssetTest.java +++ b/integration-tests/src/test/java/com/atlan/java/sdk/SQLAssetTest.java @@ -541,6 +541,19 @@ void createColumn8() throws AtlanException { assertEquals(column8.getConnectionQualifiedName(), connection.getQualifiedName()); } + @Test( + groups = {"asset.create.contract"}, + dependsOnGroups = {"asset.create.column.*"}) + void generateContract() throws AtlanException { + String tableContract = Atlan.getDefaultClient().contracts.generateInitialSpec(table); + assertNotNull(tableContract); + assertTrue(tableContract.startsWith("---")); + assertTrue(tableContract.contains("columns:")); + assertTrue(tableContract.contains(" - name: " + COLUMN_NAME1)); + assertTrue(tableContract.contains(" - name: " + COLUMN_NAME2)); + assertTrue(tableContract.endsWith("...\n")); + } + @Test( groups = {"asset.read.column.5"}, dependsOnGroups = {"asset.create.column.5"}) diff --git a/sdk/src/main/java/com/atlan/AtlanClient.java b/sdk/src/main/java/com/atlan/AtlanClient.java index 0edd0743bc..7d594c463b 100644 --- a/sdk/src/main/java/com/atlan/AtlanClient.java +++ b/sdk/src/main/java/com/atlan/AtlanClient.java @@ -170,6 +170,9 @@ public class AtlanClient { /** Endpoint with operations to interact with OpenLineage. */ public final OpenLineageEndpoint openLineage; + /** Endpoint with operations to interact with data contracts. */ + public final ContractsEndpoint contracts; + /** Client-aware asset deserializer. */ @Getter private final AssetDeserializer assetDeserializer; @@ -225,6 +228,7 @@ public class AtlanClient { tasks = new TaskEndpoint(this); sso = new SSOEndpoint(this); openLineage = new OpenLineageEndpoint(this); + contracts = new ContractsEndpoint(this); atlanTagCache = new AtlanTagCache(typeDefs); customMetadataCache = new CustomMetadataCache(typeDefs); enumCache = new EnumCache(typeDefs); diff --git a/sdk/src/main/java/com/atlan/api/ContractsEndpoint.java b/sdk/src/main/java/com/atlan/api/ContractsEndpoint.java new file mode 100644 index 0000000000..5a55a25072 --- /dev/null +++ b/sdk/src/main/java/com/atlan/api/ContractsEndpoint.java @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: Apache-2.0 + Copyright 2022 Atlan Pte. Ltd. */ +package com.atlan.api; + +import com.atlan.AtlanClient; +import com.atlan.exception.AtlanException; +import com.atlan.model.assets.Asset; +import com.atlan.model.core.AtlanObject; +import com.atlan.net.ApiResource; +import com.atlan.net.RequestOptions; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +/** + * API endpoints for data contract-specific operations. + */ +public class ContractsEndpoint extends HeraclesEndpoint { + + private static final String endpoint = "/contracts"; + + private static final String endpoint_init = endpoint + "/init"; + + public ContractsEndpoint(AtlanClient client) { + super(client); + } + + /** + * Generate an initial contract spec for the provided asset. + * The asset must have at least its qualifiedName (and type) populated. + * + * @param asset for which to generate the initial contract spec + * @return the YAML for the initial contract spec for the provided asset + * @throws AtlanException on any issue interacting with the API + */ + public String generateInitialSpec(Asset asset) throws AtlanException { + return generateInitialSpec(asset, null); + } + + /** + * Generate an initial contract spec for the provided asset. + * The asset must have at least its qualifiedName (and type) populated. + * + * @param asset for which to generate the initial contract spec + * @param options to override default client settings + * @return the YAML for the initial contract spec for the provided asset + * @throws AtlanException on any issue interacting with the API + */ + public String generateInitialSpec(Asset asset, RequestOptions options) throws AtlanException { + InitRequest request = new InitRequest(asset); + String url = String.format("%s%s", getBaseUrl(), endpoint_init); + InitResponse response = + ApiResource.request(client, ApiResource.RequestMethod.POST, url, request, InitResponse.class, options); + return response.getContract(); + } + + @Getter + @EqualsAndHashCode(callSuper = false) + private static final class InitRequest extends AtlanObject { + private static final long serialVersionUID = 2L; + String assetType; + String assetQualifiedName; + + public InitRequest(String assetType, String assetQualifiedName) { + this.assetType = assetType; + this.assetQualifiedName = assetQualifiedName; + } + + public InitRequest(Asset asset) { + this(asset.getTypeName(), asset.getQualifiedName()); + } + } + + @Getter + @EqualsAndHashCode(callSuper = false) + private static final class InitResponse extends ApiResource { + private static final long serialVersionUID = 2L; + String contract; + } +}