From 3f31fe22ec6016349772ea23f85cde7b62dc3eba Mon Sep 17 00:00:00 2001 From: "databricks-ci-ghec-1[bot]" <184311507+databricks-ci-ghec-1[bot]@users.noreply.github.com> Date: Wed, 7 Oct 2026 03:21:02 +0000 Subject: [PATCH] Release databricks-sdk-java --- .codegen/_last_sha | 2 +- .github/PULL_REQUEST_TEMPLATE.md | 2 +- .github/workflows/external-message.yml | 59 ---- .github/workflows/integration-tests.yml | 98 ------ CHANGELOG.md | 8 + CONTRIBUTING.md | 6 +- databricks-sdk-java/lockfile.json | 164 ++++----- databricks-sdk-java/pom.xml | 4 +- .../com/databricks/sdk/WorkspaceClient.java | 2 +- .../sdk/core/CredentialsProvider.java | 30 ++ .../com/databricks/sdk/core/UserAgent.java | 2 +- .../sdk/service/apps/AppDeployment.java | 19 + .../sdk/service/apps/AppHealthCheck.java | 63 ++++ .../databricks/sdk/service/ml/Feature.java | 12 +- .../sdk/service/ml/FeatureEngineeringAPI.java | 2 +- .../service/ml/FeatureEngineeringService.java | 2 +- .../sdk/service/ml/MaterializedFeature.java | 10 +- .../sdk/ComputeHttpFixtureTest.java | 124 +++++++ .../databricks/sdk/DbfsHttpFixtureTest.java | 145 ++++++++ .../databricks/sdk/FilesHttpFixtureTest.java | 152 ++++++++ .../sdk/ServingDataPlaneHttpFixtureTest.java | 119 +++++++ .../sdk/core/DatabricksConfigTest.java | 8 +- .../sdk/integration/AccountClientIT.java | 25 -- .../sdk/integration/AccountGroupsIT.java | 24 -- .../AccountMetastoreAssignmentsIT.java | 37 -- .../sdk/integration/AccountUsersIT.java | 24 -- .../sdk/integration/ClustersIT.java | 53 --- .../sdk/integration/CredentialsIT.java | 26 -- .../integration/DatabricksOidcAccountIT.java | 73 ---- .../DatabricksOidcWorkspaceIT.java | 73 ---- .../sdk/integration/DatabricksWifIT.java | 332 ------------------ .../databricks/sdk/integration/DbfsIT.java | 130 ------- .../sdk/integration/EncryptionKeysIT.java | 24 -- .../databricks/sdk/integration/FilesIT.java | 190 ---------- .../sdk/integration/HostMetadataIT.java | 41 --- .../databricks/sdk/integration/JobsIT.java | 35 -- .../sdk/integration/NetworksIT.java | 24 -- .../sdk/integration/PrivateAccessIT.java | 26 -- .../databricks/sdk/integration/QueriesIT.java | 22 -- .../databricks/sdk/integration/ReposIT.java | 23 -- .../databricks/sdk/integration/SecretsIT.java | 69 ---- .../com/databricks/sdk/integration/SqlIT.java | 44 --- .../databricks/sdk/integration/StorageIT.java | 24 -- .../sdk/integration/UnifiedHostAccountIT.java | 26 -- .../sdk/integration/UnifiedHostGroupsIT.java | 45 --- .../integration/UnifiedHostWorkspaceIT.java | 47 --- .../sdk/integration/VpcEndpointsIT.java | 26 -- .../sdk/integration/WorkspacesIT.java | 24 -- .../framework/CollectionUtils.java | 21 -- .../sdk/integration/framework/NameUtils.java | 20 -- .../framework/ResourceWithCleanup.java | 54 --- examples/docs/pom.xml | 2 +- examples/spring-boot-oauth-u2m-demo/pom.xml | 2 +- lockfile.json | 2 +- pom.xml | 40 +-- shaded/pom.xml | 2 +- 56 files changed, 783 insertions(+), 1880 deletions(-) delete mode 100644 .github/workflows/external-message.yml delete mode 100644 .github/workflows/integration-tests.yml create mode 100644 databricks-sdk-java/src/main/java/com/databricks/sdk/service/apps/AppHealthCheck.java create mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/ComputeHttpFixtureTest.java create mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/DbfsHttpFixtureTest.java create mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/FilesHttpFixtureTest.java create mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/ServingDataPlaneHttpFixtureTest.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/AccountClientIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/AccountGroupsIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/AccountMetastoreAssignmentsIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/AccountUsersIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/ClustersIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/CredentialsIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksOidcAccountIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksOidcWorkspaceIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksWifIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DbfsIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/EncryptionKeysIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/FilesIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/HostMetadataIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/JobsIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/NetworksIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/PrivateAccessIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/QueriesIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/ReposIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/SecretsIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/SqlIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/StorageIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/UnifiedHostAccountIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/UnifiedHostGroupsIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/UnifiedHostWorkspaceIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/VpcEndpointsIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/WorkspacesIT.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/framework/CollectionUtils.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/framework/NameUtils.java delete mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/framework/ResourceWithCleanup.java diff --git a/.codegen/_last_sha b/.codegen/_last_sha index 32ef965f8..c7aae7e72 100644 --- a/.codegen/_last_sha +++ b/.codegen/_last_sha @@ -1 +1 @@ -38d17606a44b9fc2e02b73e9ebc9b916998ad105 \ No newline at end of file +6d999596a730026ac6e5e8559b6fc62e35257710 \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 2ebbd89c3..1af106da1 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -65,7 +65,7 @@ ")) | .id') - echo "Previous comment IDs: $previous_comment_ids" - # Iterate over each comment ID and delete the comment - if [ ! -z "$previous_comment_ids" ]; then - echo "$previous_comment_ids" | while read -r comment_id; do - echo "Deleting comment with ID: $comment_id" - gh api "repos/${{ github.repository }}/issues/comments/$comment_id" -X DELETE - done - fi - - - name: Comment on PR - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - COMMIT_SHA: ${{ github.event.pull_request.head.sha }} - run: | - gh pr comment ${{ github.event.pull_request.number }} --body \ - " - If integration tests don't run automatically, an authorized user can run them manually by following the instructions below: - - Trigger: - [go/deco-tests-run/sdk-java](https://go/deco-tests-run/sdk-java) - - Inputs: - * PR number: ${{github.event.pull_request.number}} - * Commit SHA: \`${{ env.COMMIT_SHA }}\` - - Checks will be approved automatically on success. - " diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml deleted file mode 100644 index 2ab880101..000000000 --- a/.github/workflows/integration-tests.yml +++ /dev/null @@ -1,98 +0,0 @@ -name: Integration Tests - -on: - pull_request: - types: [opened, synchronize] - - merge_group: - -jobs: - check-token: - name: Check secrets access - - runs-on: - group: databricks-deco-testing-runner-group - labels: ubuntu-latest-deco - - environment: "test-trigger-is" - outputs: - has_token: ${{ steps.set-token-status.outputs.has_token }} - steps: - - name: Check if required secrets are set - id: set-token-status - run: | - if [ -z "${{ secrets.DECO_WORKFLOW_TRIGGER_APP_ID }}" ] || [ -z "${{ secrets.DECO_TEST_APPROVAL_APP_ID }}" ]; then - echo "Required secrets are missing. User has no access to secrets." - echo "has_token=false" >> $GITHUB_OUTPUT - else - echo "All required secrets are set. User has access to secrets." - echo "has_token=true" >> $GITHUB_OUTPUT - fi - - trigger-tests: - name: Trigger Tests - - runs-on: - group: databricks-release-runner-group-emu-access - labels: linux-ubuntu-latest-emu-access - - needs: check-token - if: github.event_name == 'pull_request' && needs.check-token.outputs.has_token == 'true' - environment: "test-trigger-is" - - steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - - - name: Generate GitHub App Token for Workflow Trigger - id: generate-token - uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1.12.0 - with: - app-id: ${{ secrets.DECO_WORKFLOW_TRIGGER_APP_ID }} - private-key: ${{ secrets.DECO_WORKFLOW_TRIGGER_PRIVATE_KEY }} - owner: ${{ secrets.ORG_NAME }} - repositories: ${{secrets.REPO_NAME}} - - - name: Trigger Workflow in Another Repo - env: - GH_TOKEN: ${{ steps.generate-token.outputs.token }} - run: | - gh workflow run sdk-java-isolated-pr.yml -R ${{ secrets.ORG_NAME }}/${{secrets.REPO_NAME}} \ - --ref main \ - -f pull_request_number=${{ github.event.pull_request.number }} \ - -f commit_sha=${{ github.event.pull_request.head.sha }} - - # Statuses and checks apply to specific commits (by hash). - # Enforcement of required checks is done both at the PR level and the merge queue level. - # In case of multiple commits in a single PR, the hash of the squashed commit - # will not match the one for the latest (approved) commit in the PR. - # We auto approve the check for the merge queue for two reasons: - # * Queue times out due to duration of tests. - # * Avoid running integration tests twice, since it was already run at the tip of the branch before squashing. - auto-approve: - if: github.event_name == 'merge_group' - - runs-on: - group: databricks-deco-testing-runner-group - labels: ubuntu-latest-deco - - permissions: - checks: write - contents: read - - steps: - - name: Auto-approve Check for Merge Queue - uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 - with: - script: | - await github.rest.checks.create({ - owner: context.repo.owner, - repo: context.repo.repo, - name: 'Integration Tests', - head_sha: context.sha, - status: 'completed', - conclusion: 'success', - output: { - title: 'Integration Tests', - summary: 'Auto-approved for merge queue (tests already passed on PR)' - } - }); diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d2f87b4b..ca11df227 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Version changelog +## Release v0.162.0 (2026-10-07) + +### Security Vulnerabilities +* Bump Jackson (`jackson.version`) from 2.18.9 to 2.18.11 to address CVE-2026-68497, CVE-2026-89407, CVE-2026-89425, CVE-2026-91776 and CVE-2026-91777. + +### API Changes +* Add `healthCheck` field for `com.databricks.sdk.service.apps.AppDeployment`. + ## Release v0.161.0 (2026-10-04) ### API Changes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b696e6ac2..b34579ede 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -97,9 +97,9 @@ log4j.logger.com.databricks.sdk=DEBUG ## Testing - All changes to the SDK should be covered by unit tests. -- When applicable, new features should be covered by integration tests. Integration tests are automatically run against Databricks workspaces and accounts in AWS, Azure and GCP. -- Integration tests should clean up after themselves. If an integration test creates a resource like a file or cluster, it should delete that resource after the test is complete. -- Integration tests should reuse compute resources where possible. +- Tests must be hermetic and must not require a live Databricks workspace or account. +- API behavior should be tested at the HTTP boundary with local fixtures when request routing, pagination, streaming, headers, or response decoding are relevant. +- Unit-level mocks remain appropriate for isolated control-flow behavior. ## Code conventions diff --git a/databricks-sdk-java/lockfile.json b/databricks-sdk-java/lockfile.json index 0c442ce52..7009cea4a 100644 --- a/databricks-sdk-java/lockfile.json +++ b/databricks-sdk-java/lockfile.json @@ -1,60 +1,60 @@ { "artifactId": "databricks-sdk-java", "groupId": "com.databricks", - "version": "0.161.0", + "version": "0.162.0", "lockFileVersion": 1, "dependencies": [ { "groupId": "com.fasterxml.jackson.core", "artifactId": "jackson-annotations", - "version": "2.18.9", + "version": "2.18.11", "checksumAlgorithm": "SHA-256", - "checksum": "798c85b86e7420d0b4eb91e7b3e37d4bee673c61de37a616ba51a7539631e6b7", + "checksum": "9eab0d36da981645392427eedcb087e13be542488e37f935723dc0be50d18a53", "scope": "provided", - "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.18.9/jackson-annotations-2.18.9.jar", - "selectedVersion": "2.18.9", + "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.18.11/jackson-annotations-2.18.11.jar", + "selectedVersion": "2.18.11", "included": true, - "id": "com.fasterxml.jackson.core:jackson-annotations:2.18.9", + "id": "com.fasterxml.jackson.core:jackson-annotations:2.18.11", "children": [] }, { "groupId": "com.fasterxml.jackson.core", "artifactId": "jackson-databind", - "version": "2.18.9", + "version": "2.18.11", "checksumAlgorithm": "SHA-256", - "checksum": "71595a3f7ff58344ec0496a9f9ec9f623ef7b85b45402d88f1ca261f1bc4b42c", + "checksum": "075ad94a76c3edf83e1972dc26f476361eb6b9d0e260d93fc11105509bc79cab", "scope": "compile", - "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.18.9/jackson-databind-2.18.9.jar", - "selectedVersion": "2.18.9", + "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.18.11/jackson-databind-2.18.11.jar", + "selectedVersion": "2.18.11", "included": true, - "id": "com.fasterxml.jackson.core:jackson-databind:2.18.9", + "id": "com.fasterxml.jackson.core:jackson-databind:2.18.11", "children": [ { "groupId": "com.fasterxml.jackson.core", "artifactId": "jackson-annotations", - "version": "2.18.9", + "version": "2.18.11", "checksumAlgorithm": "SHA-256", - "checksum": "798c85b86e7420d0b4eb91e7b3e37d4bee673c61de37a616ba51a7539631e6b7", + "checksum": "9eab0d36da981645392427eedcb087e13be542488e37f935723dc0be50d18a53", "scope": "compile", - "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.18.9/jackson-annotations-2.18.9.jar", - "selectedVersion": "2.18.9", + "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.18.11/jackson-annotations-2.18.11.jar", + "selectedVersion": "2.18.11", "included": false, - "id": "com.fasterxml.jackson.core:jackson-annotations:2.18.9", - "parent": "com.fasterxml.jackson.core:jackson-databind:2.18.9", + "id": "com.fasterxml.jackson.core:jackson-annotations:2.18.11", + "parent": "com.fasterxml.jackson.core:jackson-databind:2.18.11", "children": [] }, { "groupId": "com.fasterxml.jackson.core", "artifactId": "jackson-core", - "version": "2.18.9", + "version": "2.18.11", "checksumAlgorithm": "SHA-256", - "checksum": "e03144f48c8d5307da2894570b4972aab8c72f22440f8dcdb745be2485ce2024", + "checksum": "825fa72dfb9e2f8a642322f1390dbac22c30d15ebd6dc6b3772158821ee124eb", "scope": "compile", - "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-core/2.18.9/jackson-core-2.18.9.jar", - "selectedVersion": "2.18.9", + "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-core/2.18.11/jackson-core-2.18.11.jar", + "selectedVersion": "2.18.11", "included": true, - "id": "com.fasterxml.jackson.core:jackson-core:2.18.9", - "parent": "com.fasterxml.jackson.core:jackson-databind:2.18.9", + "id": "com.fasterxml.jackson.core:jackson-core:2.18.11", + "parent": "com.fasterxml.jackson.core:jackson-databind:2.18.11", "children": [] } ] @@ -62,41 +62,41 @@ { "groupId": "com.fasterxml.jackson.datatype", "artifactId": "jackson-datatype-guava", - "version": "2.18.9", + "version": "2.18.11", "checksumAlgorithm": "SHA-256", - "checksum": "938c72a8141375bee107405b93ad31a98ea39c7305f8f394ee41c7f240aac47f", + "checksum": "3eed4eefff6a765f87b5280cb3d6335bbc97fd12930ab39703bcc8f781c80c05", "scope": "compile", - "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/datatype/jackson-datatype-guava/2.18.9/jackson-datatype-guava-2.18.9.jar", - "selectedVersion": "2.18.9", + "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/datatype/jackson-datatype-guava/2.18.11/jackson-datatype-guava-2.18.11.jar", + "selectedVersion": "2.18.11", "included": true, - "id": "com.fasterxml.jackson.datatype:jackson-datatype-guava:2.18.9", + "id": "com.fasterxml.jackson.datatype:jackson-datatype-guava:2.18.11", "children": [ { "groupId": "com.fasterxml.jackson.core", "artifactId": "jackson-core", - "version": "2.18.9", + "version": "2.18.11", "checksumAlgorithm": "SHA-256", - "checksum": "e03144f48c8d5307da2894570b4972aab8c72f22440f8dcdb745be2485ce2024", + "checksum": "825fa72dfb9e2f8a642322f1390dbac22c30d15ebd6dc6b3772158821ee124eb", "scope": "compile", - "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-core/2.18.9/jackson-core-2.18.9.jar", - "selectedVersion": "2.18.9", + "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-core/2.18.11/jackson-core-2.18.11.jar", + "selectedVersion": "2.18.11", "included": false, - "id": "com.fasterxml.jackson.core:jackson-core:2.18.9", - "parent": "com.fasterxml.jackson.datatype:jackson-datatype-guava:2.18.9", + "id": "com.fasterxml.jackson.core:jackson-core:2.18.11", + "parent": "com.fasterxml.jackson.datatype:jackson-datatype-guava:2.18.11", "children": [] }, { "groupId": "com.fasterxml.jackson.core", "artifactId": "jackson-databind", - "version": "2.18.9", + "version": "2.18.11", "checksumAlgorithm": "SHA-256", - "checksum": "71595a3f7ff58344ec0496a9f9ec9f623ef7b85b45402d88f1ca261f1bc4b42c", + "checksum": "075ad94a76c3edf83e1972dc26f476361eb6b9d0e260d93fc11105509bc79cab", "scope": "compile", - "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.18.9/jackson-databind-2.18.9.jar", - "selectedVersion": "2.18.9", + "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.18.11/jackson-databind-2.18.11.jar", + "selectedVersion": "2.18.11", "included": false, - "id": "com.fasterxml.jackson.core:jackson-databind:2.18.9", - "parent": "com.fasterxml.jackson.datatype:jackson-datatype-guava:2.18.9", + "id": "com.fasterxml.jackson.core:jackson-databind:2.18.11", + "parent": "com.fasterxml.jackson.datatype:jackson-datatype-guava:2.18.11", "children": [] }, { @@ -110,7 +110,7 @@ "selectedVersion": "32.0.0-android", "included": false, "id": "com.google.guava:guava:25.1-jre", - "parent": "com.fasterxml.jackson.datatype:jackson-datatype-guava:2.18.9", + "parent": "com.fasterxml.jackson.datatype:jackson-datatype-guava:2.18.11", "children": [] } ] @@ -118,41 +118,41 @@ { "groupId": "com.fasterxml.jackson.datatype", "artifactId": "jackson-datatype-jdk8", - "version": "2.18.9", + "version": "2.18.11", "checksumAlgorithm": "SHA-256", - "checksum": "c0f2490297fd3d376e28eb3bdb58e8c99e4a079493f5dabd70cd0c7ab1713696", + "checksum": "efb0704bc8c9ff1eab7f1f8d0aabe3365d601b875b6dfc2a89ff750f9e0a8d2f", "scope": "compile", - "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.18.9/jackson-datatype-jdk8-2.18.9.jar", - "selectedVersion": "2.18.9", + "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.18.11/jackson-datatype-jdk8-2.18.11.jar", + "selectedVersion": "2.18.11", "included": true, - "id": "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.9", + "id": "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.11", "children": [ { "groupId": "com.fasterxml.jackson.core", "artifactId": "jackson-core", - "version": "2.18.9", + "version": "2.18.11", "checksumAlgorithm": "SHA-256", - "checksum": "e03144f48c8d5307da2894570b4972aab8c72f22440f8dcdb745be2485ce2024", + "checksum": "825fa72dfb9e2f8a642322f1390dbac22c30d15ebd6dc6b3772158821ee124eb", "scope": "compile", - "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-core/2.18.9/jackson-core-2.18.9.jar", - "selectedVersion": "2.18.9", + "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-core/2.18.11/jackson-core-2.18.11.jar", + "selectedVersion": "2.18.11", "included": false, - "id": "com.fasterxml.jackson.core:jackson-core:2.18.9", - "parent": "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.9", + "id": "com.fasterxml.jackson.core:jackson-core:2.18.11", + "parent": "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.11", "children": [] }, { "groupId": "com.fasterxml.jackson.core", "artifactId": "jackson-databind", - "version": "2.18.9", + "version": "2.18.11", "checksumAlgorithm": "SHA-256", - "checksum": "71595a3f7ff58344ec0496a9f9ec9f623ef7b85b45402d88f1ca261f1bc4b42c", + "checksum": "075ad94a76c3edf83e1972dc26f476361eb6b9d0e260d93fc11105509bc79cab", "scope": "compile", - "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.18.9/jackson-databind-2.18.9.jar", - "selectedVersion": "2.18.9", + "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.18.11/jackson-databind-2.18.11.jar", + "selectedVersion": "2.18.11", "included": false, - "id": "com.fasterxml.jackson.core:jackson-databind:2.18.9", - "parent": "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.9", + "id": "com.fasterxml.jackson.core:jackson-databind:2.18.11", + "parent": "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.11", "children": [] } ] @@ -160,55 +160,55 @@ { "groupId": "com.fasterxml.jackson.datatype", "artifactId": "jackson-datatype-jsr310", - "version": "2.18.9", + "version": "2.18.11", "checksumAlgorithm": "SHA-256", - "checksum": "1b35df59d068f97e7b89e1cc2244644ffeadbf31aff970dc112fff0cabba8e9c", + "checksum": "b2bab3e2c34f7b0b7f83bdb4de4c869c884466f756d76ed661ab3d2d9f35d1d3", "scope": "compile", - "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.18.9/jackson-datatype-jsr310-2.18.9.jar", - "selectedVersion": "2.18.9", + "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.18.11/jackson-datatype-jsr310-2.18.11.jar", + "selectedVersion": "2.18.11", "included": true, - "id": "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.9", + "id": "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.11", "children": [ { "groupId": "com.fasterxml.jackson.core", "artifactId": "jackson-annotations", - "version": "2.18.9", + "version": "2.18.11", "checksumAlgorithm": "SHA-256", - "checksum": "798c85b86e7420d0b4eb91e7b3e37d4bee673c61de37a616ba51a7539631e6b7", + "checksum": "9eab0d36da981645392427eedcb087e13be542488e37f935723dc0be50d18a53", "scope": "compile", - "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.18.9/jackson-annotations-2.18.9.jar", - "selectedVersion": "2.18.9", + "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.18.11/jackson-annotations-2.18.11.jar", + "selectedVersion": "2.18.11", "included": false, - "id": "com.fasterxml.jackson.core:jackson-annotations:2.18.9", - "parent": "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.9", + "id": "com.fasterxml.jackson.core:jackson-annotations:2.18.11", + "parent": "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.11", "children": [] }, { "groupId": "com.fasterxml.jackson.core", "artifactId": "jackson-core", - "version": "2.18.9", + "version": "2.18.11", "checksumAlgorithm": "SHA-256", - "checksum": "e03144f48c8d5307da2894570b4972aab8c72f22440f8dcdb745be2485ce2024", + "checksum": "825fa72dfb9e2f8a642322f1390dbac22c30d15ebd6dc6b3772158821ee124eb", "scope": "compile", - "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-core/2.18.9/jackson-core-2.18.9.jar", - "selectedVersion": "2.18.9", + "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-core/2.18.11/jackson-core-2.18.11.jar", + "selectedVersion": "2.18.11", "included": false, - "id": "com.fasterxml.jackson.core:jackson-core:2.18.9", - "parent": "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.9", + "id": "com.fasterxml.jackson.core:jackson-core:2.18.11", + "parent": "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.11", "children": [] }, { "groupId": "com.fasterxml.jackson.core", "artifactId": "jackson-databind", - "version": "2.18.9", + "version": "2.18.11", "checksumAlgorithm": "SHA-256", - "checksum": "71595a3f7ff58344ec0496a9f9ec9f623ef7b85b45402d88f1ca261f1bc4b42c", + "checksum": "075ad94a76c3edf83e1972dc26f476361eb6b9d0e260d93fc11105509bc79cab", "scope": "compile", - "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.18.9/jackson-databind-2.18.9.jar", - "selectedVersion": "2.18.9", + "resolved": "https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.18.11/jackson-databind-2.18.11.jar", + "selectedVersion": "2.18.11", "included": false, - "id": "com.fasterxml.jackson.core:jackson-databind:2.18.9", - "parent": "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.9", + "id": "com.fasterxml.jackson.core:jackson-databind:2.18.11", + "parent": "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.11", "children": [] } ] @@ -1275,7 +1275,7 @@ "environment": { "osName": "Linux", "mavenVersion": "3.9.14", - "javaVersion": "11.0.30" + "javaVersion": "11.0.32" }, "config": { "includeMavenPlugins": false, diff --git a/databricks-sdk-java/pom.xml b/databricks-sdk-java/pom.xml index 228a9fbce..a71d8b788 100644 --- a/databricks-sdk-java/pom.xml +++ b/databricks-sdk-java/pom.xml @@ -5,13 +5,13 @@ com.databricks databricks-sdk-parent - 0.161.0 + 0.162.0 databricks-sdk-java Databricks SDK for Java 4.5.14 - 2.18.9 + 2.18.11 5.10.0 1.8 1.8 diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/WorkspaceClient.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/WorkspaceClient.java index 8e0874242..87965e01c 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/WorkspaceClient.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/WorkspaceClient.java @@ -1047,7 +1047,7 @@ public ExternalMetadataAPI externalMetadata() { return externalMetadataAPI; } - /** [description] */ + /** Feature Engineering provides APIs for managing features and materialized features. */ public FeatureEngineeringAPI featureEngineering() { return featureEngineeringAPI; } diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/CredentialsProvider.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/CredentialsProvider.java index 0af45b481..07945dd1b 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/CredentialsProvider.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/CredentialsProvider.java @@ -1,5 +1,8 @@ package com.databricks.sdk.core; +import java.util.Objects; +import java.util.function.Function; + /** * CredentialsProvider is an interface that provides a HeaderFactory to authenticate requests to the * Databricks API. @@ -13,6 +16,33 @@ * interface should not call these methods directly. */ public interface CredentialsProvider { + /** + * Creates a credentials provider backed by a configuration function. + * + *

This is useful for custom authentication mechanisms that do not need a dedicated provider + * class. Runtime exceptions from {@code configureFn} are propagated to the caller. + * + * @param authType the authentication type used for logging and user-agent identification + * @param configureFn creates the header factory for a Databricks configuration + * @return a credentials provider backed by {@code configureFn} + */ + static CredentialsProvider from( + String authType, Function configureFn) { + Objects.requireNonNull(authType, "authType"); + Objects.requireNonNull(configureFn, "configureFn"); + return new CredentialsProvider() { + @Override + public String authType() { + return authType; + } + + @Override + public HeaderFactory configure(DatabricksConfig config) { + return configureFn.apply(config); + } + }; + } + /** * Returns the authentication type identifier for this credentials provider. * diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/UserAgent.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/UserAgent.java index 6aca696ec..af77c440c 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/UserAgent.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/UserAgent.java @@ -36,7 +36,7 @@ public String getValue() { // TODO: check if reading from // /META-INF/maven/com.databricks/databrics-sdk-java/pom.properties // or getClass().getPackage().getImplementationVersion() is enough. - private static final String version = "0.161.0"; + private static final String version = "0.162.0"; public static void withProduct(String product, String productVersion) { UserAgent.product = product; diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/apps/AppDeployment.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/apps/AppDeployment.java index bf9640846..6d7f57511 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/apps/AppDeployment.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/apps/AppDeployment.java @@ -44,6 +44,13 @@ public class AppDeployment { @JsonProperty("git_source") private GitSource gitSource; + /** + * Deploy-time health check for the app. Verifies the app is responding to HTTP requests before + * considering the deployment successful. + */ + @JsonProperty("health_check") + private AppHealthCheck healthCheck; + /** The mode of which the deployment will manage the source code. */ @JsonProperty("mode") private AppDeploymentMode mode; @@ -129,6 +136,15 @@ public GitSource getGitSource() { return gitSource; } + public AppDeployment setHealthCheck(AppHealthCheck healthCheck) { + this.healthCheck = healthCheck; + return this; + } + + public AppHealthCheck getHealthCheck() { + return healthCheck; + } + public AppDeployment setMode(AppDeploymentMode mode) { this.mode = mode; return this; @@ -177,6 +193,7 @@ public boolean equals(Object o) { && Objects.equals(deploymentId, that.deploymentId) && Objects.equals(envVars, that.envVars) && Objects.equals(gitSource, that.gitSource) + && Objects.equals(healthCheck, that.healthCheck) && Objects.equals(mode, that.mode) && Objects.equals(sourceCodePath, that.sourceCodePath) && Objects.equals(status, that.status) @@ -193,6 +210,7 @@ public int hashCode() { deploymentId, envVars, gitSource, + healthCheck, mode, sourceCodePath, status, @@ -209,6 +227,7 @@ public String toString() { .add("deploymentId", deploymentId) .add("envVars", envVars) .add("gitSource", gitSource) + .add("healthCheck", healthCheck) .add("mode", mode) .add("sourceCodePath", sourceCodePath) .add("status", status) diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/apps/AppHealthCheck.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/apps/AppHealthCheck.java new file mode 100644 index 000000000..9334ca4c1 --- /dev/null +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/apps/AppHealthCheck.java @@ -0,0 +1,63 @@ +// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT. + +package com.databricks.sdk.service.apps; + +import com.databricks.sdk.support.Generated; +import com.databricks.sdk.support.ToStringer; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.protobuf.Duration; +import java.util.Objects; + +/** Deploy-time HTTP health check configuration for an app deployment. */ +@Generated +public class AppHealthCheck { + /** HTTP path to probe, e.g. "/health" or "/api/status". */ + @JsonProperty("path") + private String path; + + /** + * Timeout to wait for the health check to pass before failing the deployment. If not set, a + * default timeout is used. + */ + @JsonProperty("timeout") + private Duration timeout; + + public AppHealthCheck setPath(String path) { + this.path = path; + return this; + } + + public String getPath() { + return path; + } + + public AppHealthCheck setTimeout(Duration timeout) { + this.timeout = timeout; + return this; + } + + public Duration getTimeout() { + return timeout; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AppHealthCheck that = (AppHealthCheck) o; + return Objects.equals(path, that.path) && Objects.equals(timeout, that.timeout); + } + + @Override + public int hashCode() { + return Objects.hash(path, timeout); + } + + @Override + public String toString() { + return new ToStringer(AppHealthCheck.class) + .add("path", path) + .add("timeout", timeout) + .toString(); + } +} diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/Feature.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/Feature.java index 681ba5b75..7a3cdf119 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/Feature.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/Feature.java @@ -27,7 +27,11 @@ public class Feature { @JsonProperty("description") private String description; - /** The entity columns for the feature, used as aggregation keys and for query-time lookup. */ + /** + * The entity columns for the feature, used as aggregation keys and for query-time lookup. + * Optional since entities are not set for RequestSource features or on-demand calculated + * features. + */ @JsonProperty("entities") private Collection entities; @@ -77,7 +81,11 @@ public class Feature { @JsonProperty("time_window") private TimeWindow timeWindow; - /** Column recording time, used for point-in-time joins, backfills, and aggregations. */ + /** + * Column recording time, used for point-in-time joins, backfills, and aggregations. Optional + * since a timeseries column is not set for RequestSource features or on-demand calculated + * features. + */ @JsonProperty("timeseries_column") private TimeseriesColumn timeseriesColumn; diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringAPI.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringAPI.java index 9dc6bbbe0..1f4aec813 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringAPI.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringAPI.java @@ -7,7 +7,7 @@ import com.databricks.sdk.support.Generated; import com.databricks.sdk.support.Paginator; -/** [description] */ +/** Feature Engineering provides APIs for managing features and materialized features. */ @Generated public class FeatureEngineeringAPI { private static final Logger LOG = LoggerFactory.getLogger(FeatureEngineeringAPI.class); diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringService.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringService.java index edadfa9cf..4b3af192e 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringService.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/FeatureEngineeringService.java @@ -4,7 +4,7 @@ import com.databricks.sdk.support.Generated; /** - * [description] + * Feature Engineering provides APIs for managing features and materialized features. * *

This is the high-level interface, that contains generated methods. * diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializedFeature.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializedFeature.java index 26765cb84..4aba8028e 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializedFeature.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/service/ml/MaterializedFeature.java @@ -61,11 +61,17 @@ public class MaterializedFeature { @JsonProperty("materialized_feature_id") private String materializedFeatureId; - /** Destination for writing feature values to an offline Delta table. */ + /** + * Destination for writing feature values to an offline Delta table. The resulting table is + * returned as `table_name`. + */ @JsonProperty("offline_store_config") private OfflineStoreConfig offlineStoreConfig; - /** Destination for writing feature values to an online Lakebase table. */ + /** + * Destination for writing feature values to an online Lakebase table. The resulting table is + * returned as `table_name`. + */ @JsonProperty("online_store_config") private OnlineStoreConfig onlineStoreConfig; diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/ComputeHttpFixtureTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/ComputeHttpFixtureTest.java new file mode 100644 index 000000000..0c55e987b --- /dev/null +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/ComputeHttpFixtureTest.java @@ -0,0 +1,124 @@ +package com.databricks.sdk; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.databricks.sdk.core.DatabricksConfig; +import com.databricks.sdk.core.DummyCredentialsProvider; +import com.databricks.sdk.core.FixtureServer; +import com.databricks.sdk.core.FixtureServer.FixtureMapping; +import com.databricks.sdk.mixin.NodeTypeSelector; +import com.databricks.sdk.mixin.SparkVersionSelector; +import com.databricks.sdk.service.compute.ClusterEvent; +import com.databricks.sdk.service.compute.GetEvents; +import com.databricks.sdk.service.jobs.BaseJob; +import com.databricks.sdk.service.jobs.ListJobsRequest; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.Test; + +class ComputeHttpFixtureTest { + @Test + void clusterSelectorsUseGeneratedHttpImplementations() throws IOException { + FixtureMapping sparkVersions = + fixture( + "GET", + "/api/2.1/clusters/spark-versions", + "{\"versions\":[" + + "{\"key\":\"14.3.x-scala2.12\",\"name\":\"14.3 LTS (includes Apache Spark 3.5.0, Scala 2.12)\"}," + + "{\"key\":\"15.4.x-scala2.12\",\"name\":\"15.4 LTS (includes Apache Spark 3.5.0, Scala 2.12)\"}]}"); + FixtureMapping nodeTypes = + fixture( + "GET", + "/api/2.1/clusters/list-node-types", + "{\"node_types\":[" + + "{\"node_type_id\":\"unavailable\",\"is_deprecated\":false,\"node_info\":{\"status\":[\"NotAvailableInRegion\"]}}," + + "{\"node_type_id\":\"available\",\"is_deprecated\":false}]}"); + + try (FixtureServer server = new FixtureServer().with(sparkVersions).with(nodeTypes)) { + WorkspaceClient workspace = workspace(server); + + assertEquals( + "15.4.x-scala2.12", + workspace.clusters().selectSparkVersion(new SparkVersionSelector().withLatest())); + assertEquals("available", workspace.clusters().selectNodeType(new NodeTypeSelector())); + server.assertAllFixturesConsumed(); + } + } + + @Test + void clusterEventsReplayServerProvidedNextRequest() throws IOException { + FixtureMapping firstPage = + new FixtureMapping.Builder() + .validateMethod("POST") + .validatePath("/api/2.1/clusters/events") + .validateBody("{\"cluster_id\":\"cluster-1\",\"page_size\":1}") + .withResponse( + "{\"events\":[{\"cluster_id\":\"cluster-1\",\"timestamp\":1}]," + + "\"next_page\":{\"cluster_id\":\"cluster-1\",\"page_size\":1,\"page_token\":\"next\"}}", + 200) + .build(); + FixtureMapping secondPage = + new FixtureMapping.Builder() + .validateMethod("POST") + .validatePath("/api/2.1/clusters/events") + .validateBody("{\"cluster_id\":\"cluster-1\",\"page_size\":1,\"page_token\":\"next\"}") + .withResponse("{\"events\":[{\"cluster_id\":\"cluster-1\",\"timestamp\":2}]}", 200) + .build(); + + try (FixtureServer server = new FixtureServer().with(firstPage).with(secondPage)) { + List timestamps = new ArrayList<>(); + for (ClusterEvent event : + workspace(server) + .clusters() + .events(new GetEvents().setClusterId("cluster-1").setPageSize(1L))) { + timestamps.add(event.getTimestamp()); + } + + assertEquals(Arrays.asList(1L, 2L), timestamps); + server.assertAllFixturesConsumed(); + } + } + + @Test + void jobsListPropagatesPageTokenAndExpansionAtHttpBoundary() throws IOException { + FixtureMapping firstPage = + fixture( + "GET", + "/api/2.2/jobs/list?expand_tasks=true&limit=1", + "{\"jobs\":[{\"job_id\":11}],\"next_page_token\":\"page two\"}"); + FixtureMapping secondPage = + fixture( + "GET", + "/api/2.2/jobs/list?expand_tasks=true&limit=1&page_token=page+two", + "{\"jobs\":[{\"job_id\":12}]}"); + + try (FixtureServer server = new FixtureServer().with(firstPage).with(secondPage)) { + List jobIds = new ArrayList<>(); + for (BaseJob job : + workspace(server).jobs().list(new ListJobsRequest().setExpandTasks(true).setLimit(1L))) { + jobIds.add(job.getJobId()); + } + + assertEquals(Arrays.asList(11L, 12L), jobIds); + server.assertAllFixturesConsumed(); + } + } + + private static WorkspaceClient workspace(FixtureServer server) { + return new WorkspaceClient( + new DatabricksConfig() + .setHost(server.getUrl()) + .setCredentialsProvider(new DummyCredentialsProvider()) + .setDisableRetries(true)); + } + + private static FixtureMapping fixture(String method, String path, String response) { + return new FixtureMapping.Builder() + .validateMethod(method) + .validatePath(path) + .withResponse(response, 200) + .build(); + } +} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/DbfsHttpFixtureTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/DbfsHttpFixtureTest.java new file mode 100644 index 000000000..5283e9d66 --- /dev/null +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/DbfsHttpFixtureTest.java @@ -0,0 +1,145 @@ +package com.databricks.sdk; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.databricks.sdk.core.DatabricksConfig; +import com.databricks.sdk.core.DummyCredentialsProvider; +import com.databricks.sdk.core.FixtureServer; +import com.databricks.sdk.core.FixtureServer.FixtureMapping; +import com.databricks.sdk.service.files.FileInfo; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Test; + +class DbfsHttpFixtureTest { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + @Test + void writeChunksDataAndClosesHandleAtHttpBoundary() throws IOException { + byte[] contents = new byte[1024 * 1024 + 3]; + Arrays.fill(contents, (byte) 'a'); + String firstBlock = Base64.getEncoder().encodeToString(Arrays.copyOf(contents, 1024 * 1024)); + String secondBlock = Base64.getEncoder().encodeToString(new byte[] {'a', 'a', 'a'}); + + FixtureMapping create = + jsonFixture( + "/api/2.0/dbfs/create", + body -> { + assertEquals("/fixture", body.get("path").asText()); + assertEquals(true, body.get("overwrite").asBoolean()); + }, + "{\"handle\":42}"); + FixtureMapping firstAddBlock = addBlockFixture(firstBlock); + FixtureMapping secondAddBlock = addBlockFixture(secondBlock); + FixtureMapping close = + jsonFixture( + "/api/2.0/dbfs/close", body -> assertEquals(42L, body.get("handle").asLong()), ""); + + try (FixtureServer server = + new FixtureServer().with(create).with(firstAddBlock).with(secondAddBlock).with(close)) { + workspace(server).dbfs().write(Paths.get("/fixture"), contents); + server.assertAllFixturesConsumed(); + } + } + + @Test + void readAndRecursiveListUseGeneratedHttpRequests() throws IOException { + String firstChunk = Base64.getEncoder().encodeToString("abc".getBytes(StandardCharsets.UTF_8)); + FixtureMapping read = + fixture( + "GET", + "/api/2.0/dbfs/read?length=1048576&offset=0&path=%2Ffixture", + "{\"bytes_read\":3,\"data\":\"" + firstChunk + "\"}"); + FixtureMapping eof = + fixture( + "GET", + "/api/2.0/dbfs/read?length=1048576&offset=3&path=%2Ffixture", + "{\"bytes_read\":0,\"data\":\"\"}"); + FixtureMapping repeatedEof = + fixture( + "GET", + "/api/2.0/dbfs/read?length=1048576&offset=3&path=%2Ffixture", + "{\"bytes_read\":0,\"data\":\"\"}"); + FixtureMapping root = + fixture( + "GET", + "/api/2.0/dbfs/list?path=%2Froot", + "{\"files\":[" + + "{\"path\":\"/root/file\",\"is_dir\":false}," + + "{\"path\":\"/root/subdir\",\"is_dir\":true}]}"); + FixtureMapping subdir = + fixture( + "GET", + "/api/2.0/dbfs/list?path=%2Froot%2Fsubdir", + "{\"files\":[{\"path\":\"/root/subdir/nested\",\"is_dir\":false}]}"); + + try (FixtureServer server = + new FixtureServer().with(read).with(eof).with(repeatedEof).with(root).with(subdir)) { + WorkspaceClient workspace = workspace(server); + assertArrayEquals( + "abc".getBytes(StandardCharsets.UTF_8), + workspace.dbfs().readAllBytes(Paths.get("/fixture"))); + + List paths = new ArrayList<>(); + for (FileInfo info : workspace.dbfs().recursiveList("/root")) { + paths.add(info.getPath()); + } + + assertEquals(Arrays.asList("/root/file", "/root/subdir", "/root/subdir/nested"), paths); + server.assertAllFixturesConsumed(); + } + } + + private static FixtureMapping addBlockFixture(String expectedData) { + return jsonFixture( + "/api/2.0/dbfs/add-block", + body -> { + assertEquals(expectedData, body.get("data").asText()); + assertEquals(42L, body.get("handle").asLong()); + }, + ""); + } + + private static FixtureMapping jsonFixture( + String path, JsonValidation validation, String response) { + return new FixtureMapping.Builder() + .validateMethod("POST") + .validatePath(path) + .validate( + exchange -> + validation.validate( + OBJECT_MAPPER.readTree( + IOUtils.toString(exchange.getRequestBody(), StandardCharsets.UTF_8)))) + .withResponse(response, 200) + .build(); + } + + private static FixtureMapping fixture(String method, String path, String response) { + return new FixtureMapping.Builder() + .validateMethod(method) + .validatePath(path) + .withResponse(response, 200) + .build(); + } + + private static WorkspaceClient workspace(FixtureServer server) { + return new WorkspaceClient( + new DatabricksConfig() + .setHost(server.getUrl()) + .setCredentialsProvider(new DummyCredentialsProvider()) + .setDisableRetries(true)); + } + + private interface JsonValidation { + void validate(JsonNode body); + } +} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/FilesHttpFixtureTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/FilesHttpFixtureTest.java new file mode 100644 index 000000000..c77bbddd6 --- /dev/null +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/FilesHttpFixtureTest.java @@ -0,0 +1,152 @@ +package com.databricks.sdk; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.databricks.sdk.core.DatabricksConfig; +import com.databricks.sdk.core.DummyCredentialsProvider; +import com.databricks.sdk.core.FixtureServer; +import com.databricks.sdk.core.FixtureServer.FixtureMapping; +import com.databricks.sdk.service.files.DirectoryEntry; +import com.databricks.sdk.service.files.DownloadResponse; +import com.databricks.sdk.service.files.GetMetadataResponse; +import com.databricks.sdk.service.files.ListDirectoryContentsRequest; +import com.databricks.sdk.service.files.UploadRequest; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Test; + +class FilesHttpFixtureTest { + private static final String FILE_PATH = "/Volumes/catalog/schema/volume/fixture.txt"; + private static final String DIRECTORY_PATH = "/Volumes/catalog/schema/volume"; + + @Test + void uploadAndDownloadPreserveRawBytesAndHeaders() throws IOException { + byte[] contents = "fixture contents".getBytes(StandardCharsets.UTF_8); + FixtureMapping upload = + new FixtureMapping.Builder() + .validateMethod("PUT") + .validatePath("/api/2.0/fs/files" + FILE_PATH) + .validateHeadersPresent( + Collections.singletonMap( + "Content-Type", Collections.singletonList("application/octet-stream"))) + .validate( + exchange -> + assertEquals( + "fixture contents", + IOUtils.toString(exchange.getRequestBody(), StandardCharsets.UTF_8))) + .withResponse("", 204) + .build(); + FixtureMapping download = + new FixtureMapping.Builder() + .validateMethod("GET") + .validatePath("/api/2.0/fs/files" + FILE_PATH) + .validateHeadersPresent( + Collections.singletonMap( + "Accept", Collections.singletonList("application/octet-stream"))) + .withResponse("fixture contents", 200) + .withResponseHeaders( + headers( + "Content-Type", + "application/octet-stream", + "Last-Modified", + "Wed, 24 Sep 2025 12:00:00 GMT")) + .build(); + + try (FixtureServer server = new FixtureServer().with(upload).with(download)) { + WorkspaceClient workspace = workspace(server); + workspace + .files() + .upload( + new UploadRequest() + .setFilePath(FILE_PATH) + .setContents(new ByteArrayInputStream(contents))); + DownloadResponse response = workspace.files().download(FILE_PATH); + + assertEquals( + "fixture contents", IOUtils.toString(response.getContents(), StandardCharsets.UTF_8)); + assertEquals("application/octet-stream", response.getContentType()); + assertEquals("Wed, 24 Sep 2025 12:00:00 GMT", response.getLastModified()); + server.assertAllFixturesConsumed(); + } + } + + @Test + void metadataAndDirectoryPaginationDecodeHttpResponses() throws IOException { + FixtureMapping metadata = + new FixtureMapping.Builder() + .validateMethod("HEAD") + .validatePath("/api/2.0/fs/files" + FILE_PATH) + .withResponse("", 200) + .withResponseHeaders( + headers( + "Content-Type", "text/plain", "Last-Modified", "Wed, 24 Sep 2025 12:00:00 GMT")) + .build(); + FixtureMapping firstPage = + fixture( + "GET", + "/api/2.0/fs/directories" + DIRECTORY_PATH + "?page_size=1", + "{\"contents\":[{\"name\":\"first.txt\",\"path\":\"" + + DIRECTORY_PATH + + "/first.txt\",\"is_directory\":false}],\"next_page_token\":\"next page\"}"); + FixtureMapping secondPage = + fixture( + "GET", + "/api/2.0/fs/directories" + DIRECTORY_PATH + "?page_size=1&page_token=next+page", + "{\"contents\":[{\"name\":\"subdir\",\"path\":\"" + + DIRECTORY_PATH + + "/subdir\",\"is_directory\":true}]}"); + + try (FixtureServer server = + new FixtureServer().with(metadata).with(firstPage).with(secondPage)) { + WorkspaceClient workspace = workspace(server); + GetMetadataResponse fileMetadata = workspace.files().getMetadata(FILE_PATH); + List names = new ArrayList<>(); + for (DirectoryEntry entry : + workspace + .files() + .listDirectoryContents( + new ListDirectoryContentsRequest() + .setDirectoryPath(DIRECTORY_PATH) + .setPageSize(1L))) { + names.add(entry.getName()); + } + + assertEquals("text/plain", fileMetadata.getContentType()); + assertEquals("Wed, 24 Sep 2025 12:00:00 GMT", fileMetadata.getLastModified()); + assertEquals(Arrays.asList("first.txt", "subdir"), names); + server.assertAllFixturesConsumed(); + } + } + + private static WorkspaceClient workspace(FixtureServer server) { + return new WorkspaceClient( + new DatabricksConfig() + .setHost(server.getUrl()) + .setCredentialsProvider(new DummyCredentialsProvider()) + .setDisableRetries(true)); + } + + private static FixtureMapping fixture(String method, String path, String response) { + return new FixtureMapping.Builder() + .validateMethod(method) + .validatePath(path) + .withResponse(response, 200) + .build(); + } + + private static Map> headers(String... namesAndValues) { + Map> result = new LinkedHashMap<>(); + for (int i = 0; i < namesAndValues.length; i += 2) { + result.put(namesAndValues[i], Collections.singletonList(namesAndValues[i + 1])); + } + return result; + } +} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/ServingDataPlaneHttpFixtureTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/ServingDataPlaneHttpFixtureTest.java new file mode 100644 index 000000000..c44a64011 --- /dev/null +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/ServingDataPlaneHttpFixtureTest.java @@ -0,0 +1,119 @@ +package com.databricks.sdk; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.databricks.sdk.core.CredentialsProvider; +import com.databricks.sdk.core.DatabricksConfig; +import com.databricks.sdk.core.FixtureServer; +import com.databricks.sdk.core.FixtureServer.FixtureMapping; +import com.databricks.sdk.core.oauth.OAuthHeaderFactory; +import com.databricks.sdk.core.oauth.Token; +import com.databricks.sdk.service.serving.QueryEndpointInput; +import com.databricks.sdk.service.serving.QueryEndpointResponse; +import java.io.IOException; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Test; + +class ServingDataPlaneHttpFixtureTest { + private static final String AUTHORIZATION_DETAILS = + "{\"type\":\"query\",\"resource\":\"route-optimized\"}"; + + @Test + void queryDiscoversEndpointExchangesTokenAndCallsDataPlane() throws IOException { + try (FixtureServer server = new FixtureServer()) { + FixtureMapping discovery = + new FixtureMapping.Builder() + .validateMethod("GET") + .validatePath("/api/2.0/serving-endpoints/route-optimized") + .validateHeadersPresent(header("Authorization", "Bearer control-plane-token")) + .withResponse( + "{\"name\":\"route-optimized\",\"data_plane_info\":{\"query_info\":{" + + "\"endpoint_url\":\"" + + server.getUrl() + + "/invocations\",\"authorization_details\":\"{\\\"type\\\":\\\"query\\\",\\\"resource\\\":\\\"route-optimized\\\"}\"}}}", + 200) + .build(); + FixtureMapping tokenExchange = + new FixtureMapping.Builder() + .validateMethod("POST") + .validatePath("/oidc/v1/token") + .validateHeadersPresent(header("Content-Type", "application/x-www-form-urlencoded")) + .validate( + exchange -> { + String decoded = + URLDecoder.decode( + IOUtils.toString(exchange.getRequestBody(), StandardCharsets.UTF_8), + StandardCharsets.UTF_8.name()); + Set parameters = new HashSet<>(Arrays.asList(decoded.split("&"))); + assertTrue( + parameters.contains( + "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer")); + assertTrue(parameters.contains("assertion=control-plane-token")); + assertTrue( + parameters.contains("authorization_details=" + AUTHORIZATION_DETAILS)); + }) + .withResponse( + "{\"access_token\":\"data-plane-token\",\"token_type\":\"Bearer\",\"expires_in\":3600}", + 200) + .build(); + FixtureMapping query = + new FixtureMapping.Builder() + .validateMethod("POST") + .validatePath("/invocations") + .validateHeadersPresent(header("Authorization", "Bearer data-plane-token")) + .validateHeadersPresent(header("X-Databricks-Workspace-Id", "123")) + .validateBody("{\"inputs\":[1.0,2.0]}") + .withResponse("{\"predictions\":[0.75]}", 200) + .withResponseHeaders(header("served-model-name", "model-v1")) + .build(); + server.with(discovery).with(tokenExchange).with(query); + + WorkspaceClient workspace = + new WorkspaceClient( + new DatabricksConfig() + .setHost(server.getUrl()) + .setWorkspaceId("123") + .setCredentialsProvider(controlPlaneCredentials()) + .setDisableAsyncTokenRefresh(true) + .setDisableRetries(true)); + QueryEndpointResponse response = + workspace + .servingEndpointsDataPlane() + .query( + new QueryEndpointInput() + .setName("route-optimized") + .setInputs(Arrays.asList(1.0, 2.0))); + + assertEquals(Collections.singletonList(0.75), response.getPredictions()); + assertEquals("model-v1", response.getServedModelName()); + assertEquals("fixture-oauth", workspace.config().getAuthType()); + server.assertAllFixturesConsumed(); + } + } + + private static CredentialsProvider controlPlaneCredentials() { + return CredentialsProvider.from( + "fixture-oauth", + config -> { + Token token = + new Token("control-plane-token", "Bearer", null, Instant.now().plusSeconds(3600)); + return OAuthHeaderFactory.fromSuppliers( + () -> token, + () -> Collections.singletonMap("Authorization", "Bearer control-plane-token")); + }); + } + + private static Map> header(String name, String value) { + return Collections.singletonMap(name, Collections.singletonList(value)); + } +} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java index d43ade2dd..aa093eec8 100644 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java @@ -91,7 +91,13 @@ public void testToStringWithEnv() { List path = new ArrayList<>(); String systemName = System.getProperty("os.name"); - DatabricksConfig config = new DatabricksConfig(); + // Host metadata discovery is unrelated to environment provenance and must stay offline here. + DatabricksConfig config = + new DatabricksConfig() + .setHttpClient( + request -> { + throw new IOException("offline test"); + }); config.resolve(new Environment(map, path, systemName)); assertEquals("Config: host=http://my.host. Env: DATABRICKS_HOST", config.toString()); } diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/AccountClientIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/AccountClientIT.java deleted file mode 100644 index bec5298fc..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/AccountClientIT.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.AccountClient; -import com.databricks.sdk.WorkspaceClient; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvOrSkip; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.iam.MeRequest; -import com.databricks.sdk.service.provisioning.Workspace; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -// Enable this test for aws-prod-acct once the issue with adding SP to non UC account is resolved -@EnvContext("ucacct") -@ExtendWith(EnvTest.class) -public class AccountClientIT { - @Test - public void getWorkspaceClient( - AccountClient a, @EnvOrSkip("TEST_WORKSPACE_ID") String workspaceIdStr) { - long workspaceId = Long.parseLong(workspaceIdStr); - Workspace workspace = a.workspaces().get(workspaceId); - WorkspaceClient w = a.getWorkspaceClient(workspace); - assert w.currentUser().me(new MeRequest()).getActive(); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/AccountGroupsIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/AccountGroupsIT.java deleted file mode 100644 index 9b2fb7a70..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/AccountGroupsIT.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.AccountClient; -import com.databricks.sdk.integration.framework.CollectionUtils; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.iam.Group; -import com.databricks.sdk.service.iam.ListAccountGroupsRequest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("account") -@ExtendWith(EnvTest.class) -public class AccountGroupsIT { - @Test - void lists(AccountClient a) { - Iterable list = - a.groups().list(new ListAccountGroupsRequest().setAttributes("displayName")); - - java.util.List all = CollectionUtils.asList(list); - - CollectionUtils.assertUnique(all); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/AccountMetastoreAssignmentsIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/AccountMetastoreAssignmentsIT.java deleted file mode 100644 index 4c0231143..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/AccountMetastoreAssignmentsIT.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.AccountClient; -import com.databricks.sdk.integration.framework.CollectionUtils; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvOrSkip; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.catalog.AccountsMetastoreAssignment; -import java.util.List; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("ucacct") -@ExtendWith(EnvTest.class) -public class AccountMetastoreAssignmentsIT { - @Test - void getAccountMetastoreAssignment( - AccountClient a, - @EnvOrSkip("TEST_WORKSPACE_ID") String workspaceId, - @EnvOrSkip("TEST_METASTORE_ID") String expectedMetastoreId) { - AccountsMetastoreAssignment assignment = - a.metastoreAssignments().get(Long.valueOf(workspaceId)); - String metastoreId = assignment.getMetastoreAssignment().getMetastoreId(); - Assertions.assertEquals(expectedMetastoreId, metastoreId); - } - - @Test - void listAccountMetastoreAssignments( - AccountClient a, - @EnvOrSkip("TEST_METASTORE_ID") String metastoreId, - @EnvOrSkip("TEST_WORKSPACE_ID") String expectedWorkspaceId) { - Iterable list = a.metastoreAssignments().list(metastoreId); - List all = CollectionUtils.asList(list); - Assertions.assertTrue(all.contains(Long.valueOf(expectedWorkspaceId))); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/AccountUsersIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/AccountUsersIT.java deleted file mode 100644 index 308ead501..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/AccountUsersIT.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.AccountClient; -import com.databricks.sdk.integration.framework.CollectionUtils; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.iam.ListAccountUsersRequest; -import com.databricks.sdk.service.iam.User; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("account") -@ExtendWith(EnvTest.class) -public class AccountUsersIT { - @Test - void lists(AccountClient a) { - Iterable list = - a.users().list(new ListAccountUsersRequest().setAttributes("displayName")); - - java.util.List all = CollectionUtils.asList(list); - - CollectionUtils.assertUnique(all); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/ClustersIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/ClustersIT.java deleted file mode 100644 index 176dc6dba..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/ClustersIT.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.databricks.sdk.integration; - -import static org.junit.jupiter.api.Assertions.*; - -import com.databricks.sdk.WorkspaceClient; -import com.databricks.sdk.core.error.platform.ResourceDoesNotExist; -import com.databricks.sdk.integration.framework.CollectionUtils; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvOrSkip; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.mixin.NodeTypeSelector; -import com.databricks.sdk.mixin.SparkVersionSelector; -import com.databricks.sdk.service.compute.ClusterEvent; -import com.databricks.sdk.service.compute.GetEvents; -import java.util.*; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("workspace") -@ExtendWith(EnvTest.class) -public class ClustersIT { - @Test - void listsEvents(WorkspaceClient w, @EnvOrSkip("TEST_DEFAULT_CLUSTER_ID") String clusterId) { - Iterable events = w.clusters().events(new GetEvents().setClusterId(clusterId)); - - List all = CollectionUtils.asList(events); - - CollectionUtils.assertUnique(all); - } - - @Test - void smallestNode(WorkspaceClient w) { - String nodeType = w.clusters().selectNodeType(new NodeTypeSelector().withLocalDisk()); - - assertNotNull(nodeType); - } - - @Test - void latestRuntime(WorkspaceClient w) { - String runtime = w.clusters().selectSparkVersion(new SparkVersionSelector().withLatest()); - - assertNotNull(runtime); - } - - @Test - void clusterDoesNotExist(WorkspaceClient w) { - assertThrowsExactly( - ResourceDoesNotExist.class, - () -> { - w.clusters().get("123-does-not-exist"); - }); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/CredentialsIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/CredentialsIT.java deleted file mode 100644 index b8a8785df..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/CredentialsIT.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.AccountClient; -import com.databricks.sdk.integration.framework.CollectionUtils; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.provisioning.Credential; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("account") -@DisabledIfEnvironmentVariable(named = "ARM_CLIENT_ID", matches = ".*") -// Skipping this test for GCP because this api is not enabled in GCP. -@DisabledIfEnvironmentVariable(named = "CLOUD_PROVIDER", matches = "GCP") -@ExtendWith(EnvTest.class) -public class CredentialsIT { - @Test - void lists(AccountClient a) { - Iterable list = a.credentials().list(); - - java.util.List all = CollectionUtils.asList(list); - - CollectionUtils.assertUnique(all); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksOidcAccountIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksOidcAccountIT.java deleted file mode 100644 index 6e7f31e66..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksOidcAccountIT.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.AccountClient; -import com.databricks.sdk.core.DatabricksConfig; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvOrSkip; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.iam.ListAccountServicePrincipalsRequest; -import com.databricks.sdk.service.iam.ServicePrincipal; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@ExtendWith(EnvTest.class) -@EnvContext("account") -public class DatabricksOidcAccountIT { - private static final Logger LOG = LoggerFactory.getLogger(DatabricksOidcAccountIT.class); - - @Test - void testAccountOAuthM2MAuth( - @EnvOrSkip("CLOUD_ENV") String cloudEnv, - @EnvOrSkip("DATABRICKS_HOST") String host, - @EnvOrSkip("DATABRICKS_ACCOUNT_ID") String accountId, - @EnvOrSkip("TEST_DATABRICKS_CLIENT_ID") String clientId, - @EnvOrSkip("TEST_DATABRICKS_CLIENT_SECRET") String clientSecret) { - LOG.info("Cloud environment: {}", cloudEnv); - - // Create account client with OAuth M2M authentication - DatabricksConfig config = - new DatabricksConfig() - .setHost(host) - .setAccountId(accountId) - .setClientId(clientId) - .setClientSecret(clientSecret) - .setAuthType("oauth-m2m"); - - AccountClient ac = new AccountClient(config); - - // List service principals to verify authentication works - Iterable servicePrincipals = - ac.servicePrincipals().list(new ListAccountServicePrincipalsRequest()); - servicePrincipals.iterator().next(); - } - - @Test - void testAccountAzureClientSecretAuth( - @EnvOrSkip("CLOUD_ENV") String cloudEnv, - @EnvOrSkip("DATABRICKS_HOST") String host, - @EnvOrSkip("DATABRICKS_ACCOUNT_ID") String accountId, - @EnvOrSkip("ARM_CLIENT_ID") String azureClientId, - @EnvOrSkip("ARM_CLIENT_SECRET") String azureClientSecret, - @EnvOrSkip("ARM_TENANT_ID") String azureTenantId) { - LOG.info("Cloud environment: {}", cloudEnv); - - // Create account client with Azure client secret authentication - DatabricksConfig config = - new DatabricksConfig() - .setHost(host) - .setAccountId(accountId) - .setAzureClientId(azureClientId) - .setAzureClientSecret(azureClientSecret) - .setAzureTenantId(azureTenantId) - .setAuthType("azure-client-secret"); - - AccountClient ac = new AccountClient(config); - - // List service principals to verify authentication works - Iterable servicePrincipals = - ac.servicePrincipals().list(new ListAccountServicePrincipalsRequest()); - servicePrincipals.iterator().next(); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksOidcWorkspaceIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksOidcWorkspaceIT.java deleted file mode 100644 index 67090eb14..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksOidcWorkspaceIT.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.databricks.sdk.integration; - -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import com.databricks.sdk.WorkspaceClient; -import com.databricks.sdk.core.DatabricksConfig; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvOrSkip; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.iam.MeRequest; -import com.databricks.sdk.service.iam.User; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@ExtendWith(EnvTest.class) -@EnvContext("ucws") -public class DatabricksOidcWorkspaceIT { - private static final Logger LOG = LoggerFactory.getLogger(DatabricksOidcWorkspaceIT.class); - - @Test - void testWorkspaceOAuthM2MAuth( - @EnvOrSkip("CLOUD_ENV") String cloudEnv, - @EnvOrSkip("DATABRICKS_HOST") String host, - @EnvOrSkip("TEST_DATABRICKS_CLIENT_ID") String clientId, - @EnvOrSkip("TEST_DATABRICKS_CLIENT_SECRET") String clientSecret) { - LOG.info("Cloud environment: {}", cloudEnv); - - // Create workspace client with OAuth M2M authentication - DatabricksConfig config = - new DatabricksConfig() - .setHost(host) - .setClientId(clientId) - .setClientSecret(clientSecret) - .setAuthType("oauth-m2m"); - - WorkspaceClient ws = new WorkspaceClient(config); - - // Call the "me" API - User me = ws.currentUser().me(new MeRequest()); - - // Verify we got a valid response - assertNotNull(me.getUserName(), "Expected non-empty UserName"); - } - - @Test - void testWorkspaceAzureClientSecretAuth( - @EnvOrSkip("CLOUD_ENV") String cloudEnv, - @EnvOrSkip("DATABRICKS_HOST") String host, - @EnvOrSkip("ARM_CLIENT_ID") String azureClientId, - @EnvOrSkip("ARM_CLIENT_SECRET") String azureClientSecret, - @EnvOrSkip("ARM_TENANT_ID") String azureTenantId) { - LOG.info("Cloud environment: {}", cloudEnv); - - // Create workspace client with Azure client secret authentication - DatabricksConfig config = - new DatabricksConfig() - .setHost(host) - .setAzureClientId(azureClientId) - .setAzureClientSecret(azureClientSecret) - .setAzureTenantId(azureTenantId) - .setAuthType("azure-client-secret"); - - WorkspaceClient ws = new WorkspaceClient(config); - - // Call the "me" API - User me = ws.currentUser().me(new MeRequest()); - - // Verify we got a valid response - assertNotNull(me.getUserName(), "Expected non-empty UserName"); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksWifIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksWifIT.java deleted file mode 100644 index 577a9d740..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksWifIT.java +++ /dev/null @@ -1,332 +0,0 @@ -package com.databricks.sdk.integration; - -import static org.junit.jupiter.api.Assertions.assertThrows; - -import com.databricks.sdk.AccountClient; -import com.databricks.sdk.WorkspaceClient; -import com.databricks.sdk.core.DatabricksConfig; -import com.databricks.sdk.core.DatabricksException; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvOrSkip; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.integration.framework.NameUtils; -import com.databricks.sdk.integration.framework.ResourceWithCleanup; -import com.databricks.sdk.service.iam.AccessControlRequest; -import com.databricks.sdk.service.iam.AccountGroup; -import com.databricks.sdk.service.iam.AccountServicePrincipal; -import com.databricks.sdk.service.iam.ComplexValue; -import com.databricks.sdk.service.iam.CreateAccountGroupRequest; -import com.databricks.sdk.service.iam.CreateAccountServicePrincipalRequest; -import com.databricks.sdk.service.iam.DeleteWorkspaceAssignmentRequest; -import com.databricks.sdk.service.iam.GrantRule; -import com.databricks.sdk.service.iam.Group; -import com.databricks.sdk.service.iam.ListAccountGroupsRequest; -import com.databricks.sdk.service.iam.MeRequest; -import com.databricks.sdk.service.iam.PermissionLevel; -import com.databricks.sdk.service.iam.RuleSetResponse; -import com.databricks.sdk.service.iam.RuleSetUpdateRequest; -import com.databricks.sdk.service.iam.ServicePrincipal; -import com.databricks.sdk.service.iam.UpdateObjectPermissions; -import com.databricks.sdk.service.iam.UpdateRuleSetRequest; -import com.databricks.sdk.service.iam.UpdateWorkspaceAssignments; -import com.databricks.sdk.service.iam.WorkspacePermission; -import com.databricks.sdk.service.oauth2.CreateServicePrincipalFederationPolicyRequest; -import com.databricks.sdk.service.oauth2.DeleteServicePrincipalFederationPolicyRequest; -import com.databricks.sdk.service.oauth2.FederationPolicy; -import com.databricks.sdk.service.oauth2.OidcFederationPolicy; -import com.databricks.sdk.service.workspace.Import; -import com.databricks.sdk.service.workspace.ImportFormat; -import com.databricks.sdk.service.workspace.Language; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Base64; -import java.util.Collections; -import java.util.UUID; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("ucacct") -@ExtendWith(EnvTest.class) -public class DatabricksWifIT { - /** Creates the GitHub OIDC configuration shared by the normal and group-assuming clients. */ - private static DatabricksConfig wifConfig(String workspaceUrl, String clientId) { - return new DatabricksConfig() - .setHost(workspaceUrl) - .setClientId(clientId) - .setAuthType("github-oidc") - .setTokenAudience("https://github.com/databricks-eng"); - } - - // Verifies that WIF can assume a group and use permissions granted only to that group, while the - // same service principal without group assumption remains denied. - @Test - void workspaceGroupAssumption( - AccountClient a, - @EnvOrSkip("TEST_WORKSPACE_ID") String workspaceIdValue, - @EnvOrSkip("TEST_WORKSPACE_URL") String workspaceUrl, - @EnvOrSkip("ACTIONS_ID_TOKEN_REQUEST_URL") String ignoredOidcRequestUrl) { - // Use the GitHub Actions OIDC environment and an account administrator to arrange the test. - long workspaceId = Long.parseLong(workspaceIdValue); - - // Create an administrator client for workspace resources and permissions. - WorkspaceClient workspaceAdmin = - new WorkspaceClient(new DatabricksConfig().setHost(workspaceUrl)); - - // Create the service principal whose normal and group-based WIF access will be tested. - AccountServicePrincipal servicePrincipal = - a.servicePrincipalsV2() - .create( - new CreateAccountServicePrincipalRequest() - .setActive(true) - .setDisplayName(NameUtils.uniqueName("java-sdk-wif-role-sp"))); - long servicePrincipalId = Long.parseLong(servicePrincipal.getId()); - - try (ResourceWithCleanup ignoredServicePrincipal = - new ResourceWithCleanup(() -> a.servicePrincipalsV2().delete(servicePrincipal.getId()))) { - // Give the service principal basic workspace access without notebook access. - a.workspaceAssignment() - .update( - new UpdateWorkspaceAssignments() - .setWorkspaceId(workspaceId) - .setPrincipalId(servicePrincipalId) - .setPermissions(Collections.singleton(WorkspacePermission.USER))); - - try (ResourceWithCleanup ignoredServicePrincipalAssignment = - new ResourceWithCleanup( - () -> - a.workspaceAssignment() - .delete( - new DeleteWorkspaceAssignmentRequest() - .setWorkspaceId(workspaceId) - .setPrincipalId(servicePrincipalId)))) { - // Create the group that represents the temporary workspace role. - AccountGroup group = - a.groupsV2() - .create( - new CreateAccountGroupRequest() - .setDisplayName(NameUtils.uniqueName("java-sdk-wif-role-group"))); - long groupId = Long.parseLong(group.getId()); - - try (ResourceWithCleanup ignoredGroup = - new ResourceWithCleanup(() -> a.groupsV2().delete(group.getId()))) { - // Assign the group to the workspace so it can receive workspace permissions. - a.workspaceAssignment() - .update( - new UpdateWorkspaceAssignments() - .setWorkspaceId(workspaceId) - .setPrincipalId(groupId) - .setPermissions(Collections.singleton(WorkspacePermission.USER))); - - try (ResourceWithCleanup ignoredGroupAssignment = - new ResourceWithCleanup( - () -> - a.workspaceAssignment() - .delete( - new DeleteWorkspaceAssignmentRequest() - .setWorkspaceId(workspaceId) - .setPrincipalId(groupId)))) { - // Grant the service principal permission to assume the group. - String ruleSetName = - String.format( - "accounts/%s/groups/%s/ruleSets/default", - a.config().getAccountId(), group.getId()); - RuleSetResponse ruleSet = a.accessControl().getRuleSet(ruleSetName, ""); - ArrayList grantRules = - ruleSet.getGrantRules() == null - ? new ArrayList<>() - : new ArrayList<>(ruleSet.getGrantRules()); - grantRules.add( - new GrantRule() - .setPrincipals( - Collections.singleton( - "servicePrincipals/" + servicePrincipal.getApplicationId())) - .setRole("roles/group.assumer")); - a.accessControl() - .updateRuleSet( - new UpdateRuleSetRequest() - .setName(ruleSetName) - .setRuleSet( - new RuleSetUpdateRequest() - .setName(ruleSetName) - .setEtag(ruleSet.getEtag()) - .setGrantRules(grantRules))); - - // Trust this repository's GitHub OIDC identity to authenticate as the service - // principal. - OidcFederationPolicy oidcPolicy = - new OidcFederationPolicy() - .setIssuer("https://token.actions.githubusercontent.com") - .setSubject( - "repo:databricks-eng/eng-dev-ecosystem:environment:integration-tests") - .setAudiences(Collections.singleton("https://github.com/databricks-eng")); - FederationPolicy federationPolicy = - a.servicePrincipalFederationPolicy() - .create( - new CreateServicePrincipalFederationPolicyRequest() - .setServicePrincipalId(servicePrincipalId) - .setPolicy(new FederationPolicy().setOidcPolicy(oidcPolicy))); - - try (ResourceWithCleanup ignoredFederationPolicy = - new ResourceWithCleanup( - () -> - a.servicePrincipalFederationPolicy() - .delete( - new DeleteServicePrincipalFederationPolicyRequest() - .setServicePrincipalId(servicePrincipalId) - .setPolicyId(federationPolicy.getUid())))) { - // Create a temporary notebook that distinguishes normal access from group access. - String adminUserName = workspaceAdmin.currentUser().me(new MeRequest()).getUserName(); - String notebookPath = - "/Users/" - + adminUserName - + "/" - + NameUtils.uniqueName("java-sdk-wif-role-notebook"); - workspaceAdmin - .workspace() - .importContent( - new Import() - .setPath(notebookPath) - .setOverwrite(true) - .setFormat(ImportFormat.SOURCE) - .setLanguage(Language.PYTHON) - .setContent( - Base64.getEncoder() - .encodeToString("print(1)".getBytes(StandardCharsets.UTF_8)))); - - try (ResourceWithCleanup ignoredNotebook = - new ResourceWithCleanup( - () -> - workspaceAdmin - .workspace() - .delete( - new com.databricks.sdk.service.workspace.Delete() - .setPath(notebookPath)))) { - // Give only the group permission to read the notebook. - Long notebookId = workspaceAdmin.workspace().getStatus(notebookPath).getObjectId(); - workspaceAdmin - .permissions() - .update( - new UpdateObjectPermissions() - .setRequestObjectType("notebooks") - .setRequestObjectId(String.valueOf(notebookId)) - .setAccessControlList( - Collections.singleton( - new AccessControlRequest() - .setGroupName(group.getDisplayName()) - .setPermissionLevel(PermissionLevel.CAN_READ)))); - - // Authenticate with the group and verify that its notebook permission is usable. - WorkspaceClient roleClient = - new WorkspaceClient( - wifConfig(workspaceUrl, servicePrincipal.getApplicationId()) - .setGroupId(group.getId())); - roleClient.workspace().getStatus(notebookPath); - - // Authenticate normally as the same service principal and verify that access is - // denied. - WorkspaceClient normalClient = - new WorkspaceClient( - wifConfig(workspaceUrl, servicePrincipal.getApplicationId())); - assertThrows( - DatabricksException.class, - () -> normalClient.workspace().getStatus(notebookPath)); - } - } - } - } - } - } - } - - // This test cannot run on local machines. We use ACTIONS_ID_TOKEN_REQUEST_URL - // to determine whether we are running in the GitHub Actions, - // and we skip the test if we are not. - @Test - void workspace( - AccountClient a, - @EnvOrSkip("TEST_WORKSPACE_ID") String workspaceId, - @EnvOrSkip("TEST_WORKSPACE_URL") String workspaceUrl, - @EnvOrSkip("ACTIONS_ID_TOKEN_REQUEST_URL") String userId) { - String spName = "java-sdk-sp" + UUID.randomUUID(); - - // Create SP with access to the workspace - ServicePrincipal sp = - a.servicePrincipals().create(new ServicePrincipal().setActive(true).setDisplayName(spName)); - - a.workspaceAssignment() - .update( - new UpdateWorkspaceAssignments() - .setWorkspaceId(Long.valueOf(workspaceId)) - .setPrincipalId(Long.valueOf(sp.getId())) - .setPermissions(Collections.singleton(WorkspacePermission.ADMIN))); - - // Setup Federation Policy - OidcFederationPolicy policy = - new OidcFederationPolicy() - .setIssuer("https://token.actions.githubusercontent.com") - .setSubject("repo:databricks-eng/eng-dev-ecosystem:environment:integration-tests") - .setAudiences(Collections.singleton("https://github.com/databricks-eng")); - - a.servicePrincipalFederationPolicy() - .create( - new CreateServicePrincipalFederationPolicyRequest() - .setServicePrincipalId(Long.valueOf(sp.getId())) - .setPolicy(new FederationPolicy().setOidcPolicy(policy))); - - // Test WIF login - DatabricksConfig config = - new DatabricksConfig() - .setHost(workspaceUrl) - .setClientId(sp.getApplicationId()) - .setAuthType("github-oidc") - .setTokenAudience("https://github.com/databricks-eng"); - - WorkspaceClient ws = new WorkspaceClient(config); - - ws.currentUser().me(new MeRequest()); - } - - // This test cannot run on local machines. We use ACTIONS_ID_TOKEN_REQUEST_URL - // to determine whether we are running in the GitHub Actions, - // and we skip the test if we are not. - @Test - void account(AccountClient a, @EnvOrSkip("ACTIONS_ID_TOKEN_REQUEST_URL") String userId) { - String spName = "java-sdk-sp" + UUID.randomUUID(); - - // Create SP - ServicePrincipal sp = - a.servicePrincipals() - .create( - new ServicePrincipal() - .setActive(true) - .setDisplayName(spName) - .setRoles(Collections.singleton(new ComplexValue().setValue("account_admin")))); - - // Setup Federation Policy - OidcFederationPolicy policy = - new OidcFederationPolicy() - .setIssuer("https://token.actions.githubusercontent.com") - .setSubject("repo:databricks-eng/eng-dev-ecosystem:environment:integration-tests") - .setAudiences(Collections.singleton("https://github.com/databricks-eng")); - - a.servicePrincipalFederationPolicy() - .create( - new CreateServicePrincipalFederationPolicyRequest() - .setServicePrincipalId(Long.valueOf(sp.getId())) - .setPolicy(new FederationPolicy().setOidcPolicy(policy))); - - // Test WIF login - DatabricksConfig config = - new DatabricksConfig() - .setHost(a.config().getHost()) - .setAccountId(a.config().getAccountId()) - .setClientId(sp.getApplicationId()) - .setAuthType("github-oidc") - .setTokenAudience("https://github.com/databricks-eng"); - - AccountClient ac = new AccountClient(config); - - Iterable groups = ac.groups().list(new ListAccountGroupsRequest()); - groups.iterator().next(); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DbfsIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DbfsIT.java deleted file mode 100644 index 1f3e9f07b..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DbfsIT.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.databricks.sdk.integration; - -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.databricks.sdk.WorkspaceClient; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.files.Delete; -import com.databricks.sdk.service.files.FileInfo; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("workspace") -@ExtendWith(EnvTest.class) -public class DbfsIT { - // An integration test for DbfsExt which writes a file of 10 KiB to DBFS, reads the written file - // back, and ensures that the contents of the file are the same as what was written out. - @Test - void writeFileAndReadFile(WorkspaceClient workspace) throws IOException { - // Generate a random file name and random contents of 10 KiB. - String fileName = "dbfs:/tmp/test-file-" + UUID.randomUUID(); - byte[] fileContents = new byte[1024 * 10]; - for (int i = 0; i < fileContents.length; i++) { - fileContents[i] = (byte) (i % 256); - } - Path path = Paths.get(fileName); - - // Write the file to DBFS. - workspace.dbfs().write(path, fileContents); - - try { - // Read the file back from DBFS. - byte[] readContents = workspace.dbfs().readAllBytes(path); - - // Assert that the contents of the file are the same as what was written out. - assertArrayEquals(fileContents, readContents); - } finally { - workspace.dbfs().delete(new Delete().setPath(fileName)); - } - } - - /** - * An integration test for DbfsExt.readAllLines which writes newline-delimited text to DBFS, reads - * the written file back, and ensures that the contents of the file are the same as what was - * written out. - */ - @Test - void writeLinesAndReadLines(WorkspaceClient workspace) throws IOException { - // Generate a random file name and random contents of 10 KiB. - String fileName = "dbfs:/tmp/test-file-" + UUID.randomUUID(); - String[] lines = new String[100]; - StringBuilder file = new StringBuilder(); - for (int i = 0; i < lines.length; i++) { - lines[i] = "line " + i; - file.append(lines[i]).append("\n"); - } - Path path = Paths.get(fileName); - - // Write the file to DBFS. - - workspace.dbfs().write(path, file.toString().getBytes(StandardCharsets.UTF_8)); - - try { - // Read the file back from DBFS. - String[] readLines = - workspace.dbfs().readAllLines(path, StandardCharsets.UTF_8).toArray(new String[0]); - - // Assert that the contents of the file are the same as what was written out. - assertArrayEquals(lines, readLines); - } finally { - workspace.dbfs().delete(new Delete().setPath(fileName)); - } - } - - /** - * An integration test which creates a directory in DBFS, creates a random set of files and - * directories within that directory, and then recursively lists the contents of the directory to - * ensure that the contents of the directory match the expected contents. - */ - @Test - void testRecursiveListing(WorkspaceClient workspace) throws IOException { - // Create a directory in DBFS. - String relativeDirectoryName = "/tmp/test-directory-" + UUID.randomUUID(); - String directoryName = "dbfs:" + relativeDirectoryName; - workspace.dbfs().mkdirs(directoryName); - try { - // Create a random set of files and directories within the directory. - workspace.dbfs().write(Paths.get(directoryName, "file1"), new byte[0]); - workspace.dbfs().write(Paths.get(directoryName, "file2"), new byte[0]); - workspace.dbfs().mkdirs(Paths.get(directoryName, "dir1").toString()); - workspace.dbfs().write(Paths.get(directoryName, "dir1", "file3"), new byte[0]); - workspace.dbfs().write(Paths.get(directoryName, "dir1", "file4"), new byte[0]); - workspace.dbfs().mkdirs(Paths.get(directoryName, "dir2").toString()); - workspace.dbfs().write(Paths.get(directoryName, "dir2", "file5"), new byte[0]); - - // List the contents of the directory recursively. - String[] expectedContents = - new String[] { - relativeDirectoryName + "/file1", - relativeDirectoryName + "/file2", - relativeDirectoryName + "/dir1", - relativeDirectoryName + "/dir1/file3", - relativeDirectoryName + "/dir1/file4", - relativeDirectoryName + "/dir2", - relativeDirectoryName + "/dir2/file5" - }; - Set expectedContentsSet = new HashSet<>(Arrays.asList(expectedContents)); - Iterable actualContents = workspace.dbfs().recursiveList(directoryName); - Set actualContentsSet = new HashSet<>(); - - // Compare actualContents to expectedContents. - for (FileInfo fileInfo : actualContents) { - actualContentsSet.add(fileInfo.getPath()); - } - assertEquals(expectedContentsSet, actualContentsSet); - } finally { - // Cleanup all the files and directories created in this test. - workspace.dbfs().delete(new Delete().setPath(directoryName).setRecursive(true)); - } - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/EncryptionKeysIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/EncryptionKeysIT.java deleted file mode 100644 index 8b7324c8e..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/EncryptionKeysIT.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.AccountClient; -import com.databricks.sdk.integration.framework.CollectionUtils; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.provisioning.CustomerManagedKey; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("account") -@DisabledIfEnvironmentVariable(named = "ARM_CLIENT_ID", matches = ".*") -@ExtendWith(EnvTest.class) -public class EncryptionKeysIT { - @Test - void lists(AccountClient a) { - Iterable list = a.encryptionKeys().list(); - - java.util.List all = CollectionUtils.asList(list); - - CollectionUtils.assertUnique(all); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/FilesIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/FilesIT.java deleted file mode 100644 index d0fdcd55d..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/FilesIT.java +++ /dev/null @@ -1,190 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.WorkspaceClient; -import com.databricks.sdk.integration.framework.CollectionUtils; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.integration.framework.NameUtils; -import com.databricks.sdk.integration.framework.ResourceWithCleanup; -import com.databricks.sdk.service.files.CreateDirectoryRequest; -import com.databricks.sdk.service.files.DirectoryEntry; -import com.databricks.sdk.service.files.GetMetadataResponse; -import com.databricks.sdk.service.files.UploadRequest; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.List; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("ucws") -@ExtendWith(EnvTest.class) -public class FilesIT { - - // An integration test for FilesApi that writes a file of 10 KiB to a configured volume, reads the - // file back, and ensures that the contents of the file are the same as what was written out. - @Test - void uploadAndDownloadFile(WorkspaceClient workspace) throws IOException { - withVolume( - workspace, - (volumePath) -> { - // Generate a random file name and random contents of 10 KiB. - String fileName = NameUtils.uniqueName(volumePath + "/test-with-?-and-#"); - byte[] fileContents = new byte[1024 * 10]; - for (int i = 0; i < fileContents.length; i++) { - fileContents[i] = (byte) (i & 0xFF); - } - ByteArrayInputStream inputStream = new ByteArrayInputStream(fileContents); - - // Write the file to DBFS. - workspace - .files() - .upload(new UploadRequest().setFilePath(fileName).setContents(inputStream)); - - // Read the file back from DBFS. - try (InputStream readContents = workspace.files().download(fileName).getContents()) { - byte[] result = new byte[fileContents.length]; - int bytesRead = readContents.read(result); - Assertions.assertEquals(bytesRead, fileContents.length); - - // Assert that the contents of the file are the same as what was written out. - Assertions.assertArrayEquals(fileContents, result); - } finally { - workspace.files().delete(fileName); - } - }); - } - - @Test - void deleteFile(WorkspaceClient workspace) throws IOException { - withVolume( - workspace, - (volumePath) -> { - String filePath = NameUtils.uniqueName(volumePath + "/some-file"); - workspace - .files() - .upload( - new UploadRequest() - .setFilePath(filePath) - .setContents(createInputStream("Hello, world!"))); - workspace.files().delete(filePath); - }); - } - - @Test - void getMetadata(WorkspaceClient workspace) throws IOException { - withVolume( - workspace, - (volumePath) -> { - String filePath = NameUtils.uniqueName(volumePath + "/some-file"); - workspace - .files() - .upload( - new UploadRequest() - .setFilePath(filePath) - .setContents(createInputStream("Hello, world!"))); - - // Check header deserialization - GetMetadataResponse metadata = workspace.files().getMetadata(filePath); - Assertions.assertEquals("application/octet-stream", metadata.getContentType()); - Assertions.assertEquals(13, metadata.getContentLength()); - Assertions.assertNotNull(metadata.getLastModified()); - }); - } - - @Test - void createDirectory(WorkspaceClient workspace) throws IOException { - withVolume( - workspace, - (volumePath) -> { - String directoryPath = NameUtils.uniqueName(volumePath + "/some-directory"); - workspace - .files() - .createDirectory(new CreateDirectoryRequest().setDirectoryPath(directoryPath)); - }); - } - - @Test - void listDirectoryContents(WorkspaceClient workspace) throws IOException { - withVolume( - workspace, - (volumePath) -> { - String fileContents = "Hello, world!"; - String directoryPath = NameUtils.uniqueName(volumePath + "/some-directory"); - workspace - .files() - .upload( - new UploadRequest() - .setFilePath(directoryPath + "/file1.txt") - .setContents(createInputStream(fileContents))); - workspace - .files() - .upload( - new UploadRequest() - .setFilePath(directoryPath + "/file2.txt") - .setContents(createInputStream(fileContents))); - workspace - .files() - .upload( - new UploadRequest() - .setFilePath(directoryPath + "/file3.txt") - .setContents(createInputStream(fileContents))); - - // List the contents of the root of the volume. - Iterable directoryEntriesIterable = - workspace.files().listDirectoryContents(directoryPath); - List directoryEntries = CollectionUtils.asList(directoryEntriesIterable); - CollectionUtils.assertUnique(directoryEntries); - Assertions.assertEquals(3, directoryEntries.size()); - }); - } - - @Test - void deleteDirectory(WorkspaceClient workspace) throws IOException { - withVolume( - workspace, - (volumePath) -> { - String directoryPath = NameUtils.uniqueName(volumePath + "/some-directory"); - workspace - .files() - .createDirectory(new CreateDirectoryRequest().setDirectoryPath(directoryPath)); - workspace.files().deleteDirectory(directoryPath); - }); - } - - @Test - void getDirectoryMetadata(WorkspaceClient workspace) throws IOException { - withVolume( - workspace, - (volumePath) -> { - String directoryPath = NameUtils.uniqueName(volumePath + "/some-directory"); - workspace - .files() - .createDirectory(new CreateDirectoryRequest().setDirectoryPath(directoryPath)); - workspace.files().getDirectoryMetadata(directoryPath); - }); - } - - /** Helper function to create an InputStream from a string. */ - private InputStream createInputStream(String text) { - return new ByteArrayInputStream(text.getBytes()); - } - - /** Run a test with against a provisioned volume */ - void withVolume(WorkspaceClient workspace, WithVolumeRunnable runnable) throws IOException { - String schemaName = NameUtils.uniqueName("filesit"); - String volumeName = NameUtils.uniqueName("filesit"); - try (ResourceWithCleanup r = - ResourceWithCleanup.makeSchema(workspace.schemas(), "main", schemaName)) { - try (ResourceWithCleanup r1 = - ResourceWithCleanup.makeVolume(workspace.volumes(), "main", schemaName, volumeName)) { - runnable.run("/Volumes/main/" + schemaName + "/" + volumeName); - } - } - } - - private interface WithVolumeRunnable { - void run(String volumePath) throws IOException; - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/HostMetadataIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/HostMetadataIT.java deleted file mode 100644 index 5c6784531..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/HostMetadataIT.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.databricks.sdk.integration; - -import static org.junit.jupiter.api.Assertions.*; - -import com.databricks.sdk.core.DatabricksConfig; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvOrSkip; -import com.databricks.sdk.integration.framework.EnvTest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Integration test for host metadata resolution via /.well-known/databricks-config. Port of Go SDK - * #1546. - */ -@ExtendWith(EnvTest.class) -@EnvContext("ucws") -public class HostMetadataIT { - private static final Logger LOG = LoggerFactory.getLogger(HostMetadataIT.class); - - @Test - void testResolvePopulatesFieldsFromMetadata(@EnvOrSkip("DATABRICKS_HOST") String host) { - DatabricksConfig config = new DatabricksConfig().setHost(host); - config.resolve(); - - LOG.info( - "Resolved metadata for {}: accountId={}, workspaceId={}, discoveryUrl={}", - host, - config.getAccountId(), - config.getWorkspaceId(), - config.getDiscoveryUrl()); - - // After resolve(), host metadata should have been resolved - assertNotNull(config.getDiscoveryUrl(), "Expected discoveryUrl to be populated after resolve"); - assertFalse(config.getDiscoveryUrl().isEmpty(), "Expected non-empty discoveryUrl"); - assertNotNull(config.getAccountId(), "Expected accountId to be populated after resolve"); - assertFalse(config.getAccountId().isEmpty(), "Expected non-empty accountId"); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/JobsIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/JobsIT.java deleted file mode 100644 index 61cf3f30b..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/JobsIT.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.databricks.sdk.integration; - -import static org.junit.jupiter.api.Assertions.*; - -import com.databricks.sdk.WorkspaceClient; -import com.databricks.sdk.core.error.platform.ResourceDoesNotExist; -import com.databricks.sdk.integration.framework.CollectionUtils; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.jobs.BaseJob; -import com.databricks.sdk.service.jobs.ListJobsRequest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("workspace") -@ExtendWith(EnvTest.class) -public class JobsIT { - @Test - void listsJobs(WorkspaceClient w) { - Iterable list = w.jobs().list(new ListJobsRequest()); - - java.util.List all = CollectionUtils.asList(list); - - CollectionUtils.assertUnique(all); - } - - @Test - void getNonExistingJob(WorkspaceClient w) { - assertThrowsExactly( - ResourceDoesNotExist.class, - () -> { - w.jobs().get(123456789); - }); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/NetworksIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/NetworksIT.java deleted file mode 100644 index 694aff04a..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/NetworksIT.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.AccountClient; -import com.databricks.sdk.integration.framework.CollectionUtils; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.provisioning.Network; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("account") -@DisabledIfEnvironmentVariable(named = "ARM_CLIENT_ID", matches = ".*") -@ExtendWith(EnvTest.class) -public class NetworksIT { - @Test - void lists(AccountClient a) { - Iterable list = a.networks().list(); - - java.util.List all = CollectionUtils.asList(list); - - CollectionUtils.assertUnique(all); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/PrivateAccessIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/PrivateAccessIT.java deleted file mode 100644 index adbcaae3a..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/PrivateAccessIT.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.AccountClient; -import com.databricks.sdk.integration.framework.CollectionUtils; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.provisioning.PrivateAccessSettings; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("account") -@DisabledIfEnvironmentVariable(named = "ARM_CLIENT_ID", matches = ".*") -// VPC Endpoints need to be enabled in our GCP E2 account. -@DisabledIfEnvironmentVariable(named = "GOOGLE_CREDENTIALS", matches = ".*") -@ExtendWith(EnvTest.class) -public class PrivateAccessIT { - @Test - void lists(AccountClient a) { - Iterable list = a.privateAccess().list(); - - java.util.List all = CollectionUtils.asList(list); - - CollectionUtils.assertUnique(all); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/QueriesIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/QueriesIT.java deleted file mode 100644 index 4d2d19725..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/QueriesIT.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.WorkspaceClient; -import com.databricks.sdk.integration.framework.CollectionUtils; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.sql.LegacyQuery; -import com.databricks.sdk.service.sql.ListQueriesLegacyRequest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("workspace") -@ExtendWith(EnvTest.class) -class QueriesIT { - @Test - void listsQueries(WorkspaceClient w) { - Iterable list = - w.queriesLegacy().list(new ListQueriesLegacyRequest().setPageSize(1000L)); - java.util.List all = CollectionUtils.asList(list); - CollectionUtils.assertUnique(all); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/ReposIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/ReposIT.java deleted file mode 100644 index 1f4b1b8e1..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/ReposIT.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.WorkspaceClient; -import com.databricks.sdk.integration.framework.CollectionUtils; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.workspace.ListReposRequest; -import com.databricks.sdk.service.workspace.RepoInfo; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("workspace") -@ExtendWith(EnvTest.class) -public class ReposIT { - @Test - void listsRepos(WorkspaceClient w) { - Iterable list = w.repos().list(new ListReposRequest()); - - java.util.List all = CollectionUtils.asList(list); - - CollectionUtils.assertUnique(all); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/SecretsIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/SecretsIT.java deleted file mode 100644 index 6257b81b2..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/SecretsIT.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.databricks.sdk.integration; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -import com.databricks.sdk.WorkspaceClient; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.integration.framework.ResourceWithCleanup; -import com.databricks.sdk.mixin.SecretsExt; -import com.databricks.sdk.service.workspace.SecretMetadata; -import com.databricks.sdk.service.workspace.SecretScope; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("workspace") -@ExtendWith(EnvTest.class) -public class SecretsIT { - @Test - void createAndGetSecretsTest(WorkspaceClient w) { - SecretsExt secretsExt = w.secrets(); - int randomSuffix = (int) (Math.random() * 1000); - String scope = "testScope-" + randomSuffix; - String key = "testKey-" + randomSuffix; - String value = "testValue-" + randomSuffix; - - try (ResourceWithCleanup ignored = ResourceWithCleanup.makeScope(secretsExt, scope)) { - - try (ResourceWithCleanup ignored1 = - ResourceWithCleanup.makeSecret(secretsExt, scope, key, value)) { - - Iterable response = secretsExt.listSecrets(scope); - boolean foundSecret = false; - for (SecretMetadata s : response) { - if (s.getKey().equals(key)) { - foundSecret = true; - break; - } - } - - assertTrue(foundSecret); - - // TODO: Uncomment once secrets.get is enabled - // String responseValue = secretResource.secretsExt.get(scope, key); - // assertEquals(value, responseValue); - } - } - } - - @Test - void createAndListScopesTest(WorkspaceClient w) { - SecretsExt secretsExt = w.secrets(); - int randomSuffix = (int) (Math.random() * 1000); - String scope = "testScope-" + randomSuffix; - - try (ResourceWithCleanup ignored = ResourceWithCleanup.makeScope(secretsExt, scope)) { - - Iterable response = secretsExt.listScopes(); - boolean foundScope = false; - for (SecretScope s : response) { - if (s.getName().equals(scope)) { - foundScope = true; - break; - } - } - - assertTrue(foundScope); - } - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/SqlIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/SqlIT.java deleted file mode 100644 index 8d99f452d..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/SqlIT.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.WorkspaceClient; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.sql.ListQueryHistoryRequest; -import com.databricks.sdk.service.sql.QueryFilter; -import com.databricks.sdk.service.sql.QueryInfo; -import com.databricks.sdk.service.sql.TimeRange; -import java.util.Arrays; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("workspace") -@ExtendWith(EnvTest.class) -public class SqlIT { - @Test - void listQueryHistoryTimeRange(WorkspaceClient w) { - TimeRange timeRange = - new TimeRange().setStartTimeMs(1690243200000L).setEndTimeMs(1690329600000L); - ListQueryHistoryRequest request = - new ListQueryHistoryRequest() - .setFilterBy(new QueryFilter().setQueryStartTimeRange(timeRange)); - Iterable queries = w.queryHistory().list(request).getRes(); - if (queries != null) { - for (QueryInfo query : queries) { - System.out.println(query); - } - } - } - - @Test - void listQueryHistoryUserIds(WorkspaceClient w) { - ListQueryHistoryRequest request = - new ListQueryHistoryRequest() - .setFilterBy(new QueryFilter().setUserIds(Arrays.asList(123L, 456L))); - Iterable queries = w.queryHistory().list(request).getRes(); - if (queries != null) { - for (QueryInfo query : queries) { - System.out.println(query); - } - } - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/StorageIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/StorageIT.java deleted file mode 100644 index c82bcdee5..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/StorageIT.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.AccountClient; -import com.databricks.sdk.integration.framework.CollectionUtils; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.provisioning.StorageConfiguration; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("account") -@DisabledIfEnvironmentVariable(named = "ARM_CLIENT_ID", matches = ".*") -@ExtendWith(EnvTest.class) -public class StorageIT { - @Test - void lists(AccountClient a) { - Iterable list = a.storage().list(); - - java.util.List all = CollectionUtils.asList(list); - - CollectionUtils.assertUnique(all); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/UnifiedHostAccountIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/UnifiedHostAccountIT.java deleted file mode 100644 index a102edfc2..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/UnifiedHostAccountIT.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.AccountClient; -import com.databricks.sdk.core.DatabricksConfig; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.iam.Group; -import com.databricks.sdk.service.iam.ListAccountGroupsRequest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("account") -@ExtendWith(EnvTest.class) -@EnabledIfEnvironmentVariable(named = "UNIFIED_HOST", matches = ".+") -public class UnifiedHostAccountIT { - @Test - void listGroups(AccountClient a) { - String unifiedHost = System.getenv("UNIFIED_HOST"); - DatabricksConfig cfg = a.config(); - cfg.setHost(unifiedHost); - - Iterable groups = a.groups().list(new ListAccountGroupsRequest()); - assert groups.iterator().hasNext(); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/UnifiedHostGroupsIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/UnifiedHostGroupsIT.java deleted file mode 100644 index a1fa61aec..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/UnifiedHostGroupsIT.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.databricks.sdk.integration; - -import static org.junit.jupiter.api.Assertions.*; - -import com.databricks.sdk.AccountClient; -import com.databricks.sdk.WorkspaceClient; -import com.databricks.sdk.core.DatabricksConfig; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvOrSkip; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.iam.Group; -import com.databricks.sdk.service.iam.ListGroupsRequest; -import java.util.Iterator; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable; -import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("account") -@ExtendWith(EnvTest.class) -@EnabledIfEnvironmentVariable(named = "UNIFIED_HOST", matches = ".+") -public class UnifiedHostGroupsIT { - @Test - @DisabledIfEnvironmentVariable(named = "CLOUD_PROVIDER", matches = "GCP") - void listWorkspaceGroupsViaUnifiedHost( - AccountClient a, - @EnvOrSkip("UNIFIED_HOST") String unifiedHost, - @EnvOrSkip("TEST_WORKSPACE_ID") String workspaceId, - @EnvOrSkip("TEST_ACCOUNT_ID") String accountId) { - DatabricksConfig config = - new DatabricksConfig() - .setHost(unifiedHost) - .setClientId(a.config().getClientId()) - .setClientSecret(a.config().getClientSecret()) - .setWorkspaceId(workspaceId) - .setAccountId(accountId); - WorkspaceClient ws = new WorkspaceClient(config); - - Iterable groups = ws.groups().list(new ListGroupsRequest().setAttributes("displayName")); - Iterator it = groups.iterator(); - assertTrue(it.hasNext(), "Expected at least one group"); - Group first = it.next(); - assertNotNull(first.getDisplayName()); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/UnifiedHostWorkspaceIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/UnifiedHostWorkspaceIT.java deleted file mode 100644 index 3af6e46fa..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/UnifiedHostWorkspaceIT.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.databricks.sdk.integration; - -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import com.databricks.sdk.AccountClient; -import com.databricks.sdk.WorkspaceClient; -import com.databricks.sdk.core.DatabricksConfig; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvOrSkip; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.iam.MeRequest; -import com.databricks.sdk.service.iam.User; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable; -import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("account") -@ExtendWith(EnvTest.class) -@EnabledIfEnvironmentVariable(named = "UNIFIED_HOST", matches = ".+") -public class UnifiedHostWorkspaceIT { - // google-credentials uses a GCP ID token with target_audience=cfg.host. - // On the unified host this produces the same token for both account and workspace - // requests (identical OIDC exchange, identical audience). Account-level APIs accept - // this token, but workspace-level APIs return 401. The X-Databricks-Workspace-Id header - // is set correctly. This appears to be a server-side limitation on unified hosts. - @Test - @DisabledIfEnvironmentVariable(named = "CLOUD_PROVIDER", matches = "GCP") - void currentUserMe( - AccountClient a, - @EnvOrSkip("UNIFIED_HOST") String unifiedHost, - @EnvOrSkip("TEST_WORKSPACE_ID") String workspaceId, - @EnvOrSkip("TEST_ACCOUNT_ID") String accountId) { - DatabricksConfig config = - new DatabricksConfig() - .setHost(unifiedHost) - .setClientId(a.config().getClientId()) - .setClientSecret(a.config().getClientSecret()) - .setWorkspaceId(workspaceId) - .setAccountId(accountId); - - WorkspaceClient ws = new WorkspaceClient(config); - - User me = ws.currentUser().me(new MeRequest()); - assertNotNull(me.getUserName(), "Expected non-empty UserName"); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/VpcEndpointsIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/VpcEndpointsIT.java deleted file mode 100644 index 411e2383e..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/VpcEndpointsIT.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.AccountClient; -import com.databricks.sdk.integration.framework.CollectionUtils; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.provisioning.VpcEndpoint; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("account") -@DisabledIfEnvironmentVariable(named = "ARM_CLIENT_ID", matches = ".*") -// VPC Endpoints need to be enabled in our GCP E2 account. -@DisabledIfEnvironmentVariable(named = "GOOGLE_CREDENTIALS", matches = ".*") -@ExtendWith(EnvTest.class) -public class VpcEndpointsIT { - @Test - void lists(AccountClient a) { - Iterable list = a.vpcEndpoints().list(); - - java.util.List all = CollectionUtils.asList(list); - - CollectionUtils.assertUnique(all); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/WorkspacesIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/WorkspacesIT.java deleted file mode 100644 index b3b08a690..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/WorkspacesIT.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.databricks.sdk.integration; - -import com.databricks.sdk.AccountClient; -import com.databricks.sdk.integration.framework.CollectionUtils; -import com.databricks.sdk.integration.framework.EnvContext; -import com.databricks.sdk.integration.framework.EnvTest; -import com.databricks.sdk.service.provisioning.Workspace; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable; -import org.junit.jupiter.api.extension.ExtendWith; - -@EnvContext("account") -@DisabledIfEnvironmentVariable(named = "ARM_CLIENT_ID", matches = ".*") -@ExtendWith(EnvTest.class) -public class WorkspacesIT { - @Test - void listsWorkspaces(AccountClient a) { - Iterable list = a.workspaces().list(); - - java.util.List all = CollectionUtils.asList(list); - - CollectionUtils.assertUnique(all); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/framework/CollectionUtils.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/framework/CollectionUtils.java deleted file mode 100644 index e278071ae..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/framework/CollectionUtils.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.databricks.sdk.integration.framework; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class CollectionUtils { - public static List asList(Iterable it) { - List all = new ArrayList<>(); - it.forEach(all::add); - return all; - } - - public static void assertUnique(List all) { - Set unique = new HashSet<>(all); - assertEquals(unique.size(), all.size(), "Items are not unique"); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/framework/NameUtils.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/framework/NameUtils.java deleted file mode 100644 index 73ee0c801..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/framework/NameUtils.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.databricks.sdk.integration.framework; - -import java.security.SecureRandom; - -public class NameUtils { - // Generates a unique name by appending a random string to the given prefix. - public static String uniqueName(String prefix) { - return prefix + "-" + generateRandomBase16String(16); - } - - public static String generateRandomBase16String(int length) { - byte[] bytes = new byte[length / 2]; - new SecureRandom().nextBytes(bytes); - StringBuilder hexBuilder = new StringBuilder(length); - for (byte b : bytes) { - hexBuilder.append(String.format("%02x", b)); - } - return hexBuilder.toString(); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/framework/ResourceWithCleanup.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/framework/ResourceWithCleanup.java deleted file mode 100644 index 28d661200..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/framework/ResourceWithCleanup.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.databricks.sdk.integration.framework; - -import com.databricks.sdk.mixin.SecretsExt; -import com.databricks.sdk.service.catalog.CreateSchema; -import com.databricks.sdk.service.catalog.CreateVolumeRequestContent; -import com.databricks.sdk.service.catalog.SchemasAPI; -import com.databricks.sdk.service.catalog.VolumeType; -import com.databricks.sdk.service.catalog.VolumesAPI; -import com.databricks.sdk.service.workspace.CreateScope; -import com.databricks.sdk.service.workspace.DeleteSecret; -import com.databricks.sdk.service.workspace.PutSecret; - -public class ResourceWithCleanup implements AutoCloseable { - private final Runnable cleanup; - - public ResourceWithCleanup(Runnable cleanup) { - this.cleanup = cleanup; - } - - public static ResourceWithCleanup makeSecret( - SecretsExt secretsExt, String scope, String key, String value) { - secretsExt.putSecret(new PutSecret().setScope(scope).setKey(key).setStringValue(value)); - return new ResourceWithCleanup( - () -> secretsExt.deleteSecret(new DeleteSecret().setScope(scope).setKey(key))); - } - - public static ResourceWithCleanup makeScope(SecretsExt secretsExt, String scope) { - secretsExt.createScope(new CreateScope().setScope(scope)); - return new ResourceWithCleanup(() -> secretsExt.deleteScope(scope)); - } - - public static ResourceWithCleanup makeSchema( - SchemasAPI schemasAPI, String catalogName, String schemaName) { - schemasAPI.create(new CreateSchema().setName(schemaName).setCatalogName(catalogName)); - return new ResourceWithCleanup(() -> schemasAPI.delete(catalogName + "." + schemaName)); - } - - public static ResourceWithCleanup makeVolume( - VolumesAPI volumesAPI, String catalogName, String schemaName, String volumeName) { - volumesAPI.create( - new CreateVolumeRequestContent() - .setCatalogName(catalogName) - .setSchemaName(schemaName) - .setName(volumeName) - .setVolumeType(VolumeType.MANAGED)); - return new ResourceWithCleanup( - () -> volumesAPI.delete(catalogName + "." + schemaName + "." + volumeName)); - } - - @Override - public void close() { - cleanup.run(); - } -} diff --git a/examples/docs/pom.xml b/examples/docs/pom.xml index e8f3cb962..90c1e1dcf 100644 --- a/examples/docs/pom.xml +++ b/examples/docs/pom.xml @@ -24,7 +24,7 @@ com.databricks databricks-sdk-java - 0.161.0 + 0.162.0 diff --git a/examples/spring-boot-oauth-u2m-demo/pom.xml b/examples/spring-boot-oauth-u2m-demo/pom.xml index 4056a1d0c..a259a1817 100644 --- a/examples/spring-boot-oauth-u2m-demo/pom.xml +++ b/examples/spring-boot-oauth-u2m-demo/pom.xml @@ -40,7 +40,7 @@ com.databricks databricks-sdk-java - 0.161.0 + 0.162.0 diff --git a/lockfile.json b/lockfile.json index f9a731cf3..217bb2780 100644 --- a/lockfile.json +++ b/lockfile.json @@ -1,7 +1,7 @@ { "artifactId": "databricks-sdk-parent", "groupId": "com.databricks", - "version": "0.161.0", + "version": "0.162.0", "lockFileVersion": 1, "dependencies": [], "mavenPlugins": [], diff --git a/pom.xml b/pom.xml index a8daef099..b3d1f4074 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.databricks databricks-sdk-parent - 0.161.0 + 0.162.0 pom Databricks SDK for Java The Databricks SDK for Java includes functionality to accelerate development with Java for @@ -89,29 +89,6 @@ - - maven-failsafe-plugin - 3.2.5 - - - - **/benchmark/** - - 4 - - - - - integration-test - verify - - integration-test - - - org.jacoco jacoco-maven-plugin @@ -184,21 +161,6 @@ - - run-integration-tests - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.1.2 - - true - - - - - release diff --git a/shaded/pom.xml b/shaded/pom.xml index fa177631c..2c04626c2 100644 --- a/shaded/pom.xml +++ b/shaded/pom.xml @@ -4,7 +4,7 @@ 4.0.0 - 0.161.0 + 0.162.0 com.databricks