Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
6ad27d7
add libraries field for Clusters
Sankalp-Mittal Aug 24, 2026
352669b
Recognize clusters.libraries as a sub-resource node
Sankalp-Mittal Aug 25, 2026
6d0278d
Add clusters.libraries direct-engine child resource
Sankalp-Mittal Aug 25, 2026
7c9526f
Model cluster libraries endpoints in testserver
Sankalp-Mittal Aug 25, 2026
da49387
Wire cluster libraries into the wheel build/upload pipeline
Sankalp-Mittal Aug 25, 2026
fc3d5c0
Reject cluster libraries under the terraform engine
Sankalp-Mittal Aug 25, 2026
3fa6fb1
Regenerate terraform<->DABs field map for cluster libraries
Sankalp-Mittal Aug 25, 2026
0771bfe
Add acceptance tests and changelog for cluster libraries
Sankalp-Mittal Aug 25, 2026
8c5552a
Fix lint in cluster_libraries (exhaustive switch, exhaustruct)
Sankalp-Mittal Aug 25, 2026
fe179e8
Add cloud drift check for cluster libraries
Sankalp-Mittal Aug 25, 2026
44a37b8
Regenerate refschema and required_fields for cluster libraries
Sankalp-Mittal Aug 25, 2026
033c26d
Scope libraries sub-resource to clusters only
Sankalp-Mittal Aug 25, 2026
25f701e
Scope libraries entry in ResourcesTypes to clusters
Sankalp-Mittal Aug 25, 2026
612add7
Cover clusters.libraries in invariant suite; commit wheel fixture
Sankalp-Mittal Aug 25, 2026
a0b4f3a
Restart cluster on library change so it takes effect
Sankalp-Mittal Aug 31, 2026
3e32ae9
Add acceptance tests for cluster library restart
Sankalp-Mittal Aug 31, 2026
0150cc9
Merge branch 'main' into sankalp-mittal/all-purpose-cluster-libraries
Sankalp-Mittal Aug 31, 2026
ed672d7
Fix exhaustruct lint on RestartCluster literal
Sankalp-Mittal Aug 31, 2026
690aa62
update comment
Sankalp-Mittal Aug 31, 2026
5ee3448
Narrow libraries-stopped-cluster request filter to fix Windows
Sankalp-Mittal Aug 31, 2026
3ba91b8
update comments
Sankalp-Mittal Aug 31, 2026
f2a022a
Exclude cluster_libraries from continue_293 backward-compat invariant
Sankalp-Mittal Aug 31, 2026
bbbe43a
Scope libraries sub-resource split to clusters in splitResourcePath
Sankalp-Mittal Aug 31, 2026
1b80d85
Include repo/exclusions in cluster library identity key
Sankalp-Mittal Aug 31, 2026
078f022
Skip clusters.libraries from parent walk in refschema dump
Sankalp-Mittal Aug 31, 2026
00895fe
Remove redundant libraries-drift acceptance test
Sankalp-Mittal Aug 31, 2026
7f40ac8
Run cluster-libraries acceptance tests on cloud
Sankalp-Mittal Aug 31, 2026
a9213b6
Manage cluster libraries as part of the cluster, not a sub-resource
Sankalp-Mittal Aug 31, 2026
2219d01
Document unhandled same-path wheel-content change for cluster libraries
Sankalp-Mittal Sep 1, 2026
6a2fba2
Add cluster-libraries restart-matrix acceptance test
Sankalp-Mittal Sep 1, 2026
8e8cce3
Merge remote-tracking branch 'origin/main' into sankalp-mittal/all-pu…
Sankalp-Mittal Sep 1, 2026
aa6aa83
Add DMS env-matrix to cluster-libraries out.test.toml; drop dead cont…
Sankalp-Mittal Sep 1, 2026
cc24040
undo unecessary change
Sankalp-Mittal Sep 1, 2026
35a1d8a
revert unecessary changes
Sankalp-Mittal Sep 1, 2026
ff961cd
revert pointless change
Sankalp-Mittal Sep 1, 2026
ccb2b43
add bracket
Sankalp-Mittal Sep 1, 2026
c8af56d
remove old test
Sankalp-Mittal Sep 1, 2026
d203128
Remove dead libraries sub-resource test scaffolding
Sankalp-Mittal Sep 1, 2026
7b3fe0b
update comment
Sankalp-Mittal Sep 1, 2026
82ea834
Title the deploy phase in libraries-repo acceptance test
Sankalp-Mittal Sep 1, 2026
fe8d2dc
update nextchanges
Sankalp-Mittal Sep 1, 2026
a3c0885
Add READPLAN variant to cluster-libraries acceptance tests
Sankalp-Mittal Sep 1, 2026
917ed09
Merge branch 'main' into sankalp-mittal/all-purpose-cluster-libraries
Sankalp-Mittal Sep 1, 2026
99d38d4
make calls in parallel
Sankalp-Mittal Sep 2, 2026
032ae53
list known limitation
Sankalp-Mittal Sep 2, 2026
5ffa620
add a test for bad behaviour
Sankalp-Mittal Sep 2, 2026
35b7b8c
mark tests as slow
Sankalp-Mittal Sep 2, 2026
840fcf3
Merge branch 'main' into sankalp-mittal/all-purpose-cluster-libraries
Sankalp-Mittal Sep 7, 2026
917219f
update nextchanges
Sankalp-Mittal Sep 7, 2026
112f4c6
update nextchanges
Sankalp-Mittal Sep 7, 2026
003b598
Drop READPLAN from wheel tests; add deploy --plan upload tripwire
Sankalp-Mittal Sep 7, 2026
459f91a
Fix changelog fragment format for cluster libraries
Sankalp-Mittal Sep 7, 2026
dca4944
delete useless test
Sankalp-Mittal Sep 7, 2026
bb35c3a
update test
Sankalp-Mittal Sep 7, 2026
fe3505d
Merge branch 'main' into sankalp-mittal/all-purpose-cluster-libraries
Sankalp-Mittal Sep 7, 2026
42c0fa9
Print a pass-line confirmation in LOG-routed cluster library tests
Sankalp-Mittal Sep 8, 2026
b2decfe
remove python3 allias
Sankalp-Mittal Sep 8, 2026
3e966a7
Capture the cluster restart request in library tests
Sankalp-Mittal Sep 8, 2026
e25a954
Stop snapshotting the plan file in the readplan tripwire
Sankalp-Mittal Sep 8, 2026
97e7e8c
Merge branch 'main' into sankalp-mittal/all-purpose-cluster-libraries
Sankalp-Mittal Sep 8, 2026
18166f7
increase timeout for test
Sankalp-Mittal Sep 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .nextchanges/bundles/cluster-libraries.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Add libraries field to clusters. ([#6365](https://github.com/databricks/cli/pull/6365))
14 changes: 14 additions & 0 deletions acceptance/bundle/invariant/configs/cluster_libraries.yml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
bundle:
name: test-bundle-$UNIQUE_NAME

resources:
clusters:
foo:
cluster_name: test-cluster-$UNIQUE_NAME
spark_version: 13.3.x-scala2.12
node_type_id: $NODE_TYPE_ID
instance_pool_id: $TEST_INSTANCE_POOL_ID
num_workers: 1
libraries:
- pypi:
package: requests
3 changes: 3 additions & 0 deletions acceptance/bundle/invariant/continue_293/test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ EnvMatrixExclude.no_instance_pool = ["INPUT_CONFIG=instance_pool.yml.tmpl"]
# cluster_policies resource is not supported on v0.293.0
EnvMatrixExclude.no_cluster_policy = ["INPUT_CONFIG=cluster_policy.yml.tmpl"]

# cluster libraries (clusters.libraries) are not supported on v0.293.0
EnvMatrixExclude.no_cluster_libraries = ["INPUT_CONFIG=cluster_libraries.yml.tmpl"]

# job_runs resource is not supported on v0.293.0
EnvMatrixExclude.no_job_run = ["INPUT_CONFIG=job_run.yml.tmpl"]

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions acceptance/bundle/invariant/migrate/test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ EnvMatrixExclude.no_genie_space = ["INPUT_CONFIG=genie_space.yml.tmpl"]
EnvMatrixExclude.no_instance_pool = ["INPUT_CONFIG=instance_pool.yml.tmpl"]
# Cluster policies are direct-only; the terraform deploy that seeds the migration fails for them.
EnvMatrixExclude.no_cluster_policy = ["INPUT_CONFIG=cluster_policy.yml.tmpl"]
# Cluster libraries are direct-only; the terraform deploy that seeds the migration fails for them.
EnvMatrixExclude.no_cluster_libraries = ["INPUT_CONFIG=cluster_libraries.yml.tmpl"]

# Cross-resource permission references (e.g. ${resources.jobs.job_b.permissions[0].level})
# don't work in terraform mode: the terraform interpolator converts the path to
Expand Down
1 change: 1 addition & 0 deletions acceptance/bundle/invariant/no_drift/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions acceptance/bundle/invariant/test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ EnvMatrix.INPUT_CONFIG = [
"catalog_optional_fields.yml.tmpl",
"cluster.yml.tmpl",
"cluster_apply_policy_default_values.yml.tmpl",
"cluster_libraries.yml.tmpl",
"cluster_policy.yml.tmpl",
"dashboard.yml.tmpl",
"job_apply_policy_default_values_job_cluster.yml.tmpl",
Expand Down
17 changes: 17 additions & 0 deletions acceptance/bundle/refschema/out.fields.txt
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,23 @@ resources.clusters.*.jdbc_port int REMOTE
resources.clusters.*.kind compute.Kind ALL
resources.clusters.*.last_restarted_time int64 REMOTE
resources.clusters.*.last_state_loss_time int64 REMOTE
resources.clusters.*.libraries []compute.Library ALL
resources.clusters.*.libraries[*] compute.Library ALL
resources.clusters.*.libraries[*].cran *compute.RCranLibrary ALL
resources.clusters.*.libraries[*].cran.package string ALL
resources.clusters.*.libraries[*].cran.repo string ALL
resources.clusters.*.libraries[*].egg string ALL
resources.clusters.*.libraries[*].jar string ALL
resources.clusters.*.libraries[*].maven *compute.MavenLibrary ALL
resources.clusters.*.libraries[*].maven.coordinates string ALL
resources.clusters.*.libraries[*].maven.exclusions []string ALL
resources.clusters.*.libraries[*].maven.exclusions[*] string ALL
resources.clusters.*.libraries[*].maven.repo string ALL
resources.clusters.*.libraries[*].pypi *compute.PythonPyPiLibrary ALL
resources.clusters.*.libraries[*].pypi.package string ALL
resources.clusters.*.libraries[*].pypi.repo string ALL
resources.clusters.*.libraries[*].requirements string ALL
resources.clusters.*.libraries[*].whl string ALL
resources.clusters.*.lifecycle *dresources.StateLifecycle REMOTE STATE
resources.clusters.*.lifecycle *resources.LifecycleWithStarted INPUT
resources.clusters.*.lifecycle resources.Lifecycle INPUT
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
bundle:
name: cluster-libraries-$UNIQUE_NAME

workspace:
root_path: ~/.bundle/$UNIQUE_NAME

artifacts:
my_test_code:
type: whl
path: .
# Use 'python' because 'python3' does not exist in Windows virtualenvs.
build: python setup.py bdist_wheel

resources:
clusters:
mycluster:
cluster_name: mycluster-$UNIQUE_NAME
spark_version: $DEFAULT_SPARK_VERSION
node_type_id: $NODE_TYPE_ID
num_workers: 1
data_security_mode: $DATA_SECURITY_MODE
libraries:
- whl: ./dist/*.whl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
__version__ = "0.0.1"
__author__ = "Databricks"
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
The entry point of the Python Wheel
"""

import sys


def main():
# This method will print the provided arguments
print("Hello from my func")
print("Got arguments:")
print(sys.argv)


if __name__ == "__main__":
main()

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

=== Deploy a cluster with a local wheel library
OK: cluster created with wheel

>>> print_requests.py //libraries/install
{
"method": "POST",
"path": "/api/2.0/libraries/install",
"body": {
"cluster_id": "[UUID]",
"libraries": [
{
"whl": "/Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/artifacts/.internal/my_test_code-0.0.1-py3-none-any.whl"
}
]
}
}

=== Badness: wheel code changes but version does not, so redeploy neither reinstalls nor restarts
OK: no restart on content-only change (known limitation)

>>> print_requests.py //libraries/install

>>> [CLI] bundle destroy --auto-approve
The following resources will be deleted:
delete resources.clusters.mycluster

All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]

Destroy: 1 deleted
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export DATA_SECURITY_MODE=USER_ISOLATION
envsubst < databricks.yml.tmpl > databricks.yml

cleanup() {
trace $CLI bundle destroy --auto-approve
rm -f out.requests.txt
}
trap cleanup EXIT

# Deploy output goes to LOG (differs fake vs cloud); echo a pass line instead.
title "Deploy a cluster with a local wheel library"
$CLI bundle deploy &> LOG.deploy
cat LOG.deploy | contains.py "Created clusters.mycluster" > /dev/null
printf '\n%s\n' "OK: cluster created with wheel"
trace print_requests.py //libraries/install

# Change only the wheel's code, keeping version 0.0.1 so the built filename - and
# thus the uploaded workspace path - is byte-for-byte identical to the first deploy.
title "Badness: wheel code changes but version does not, so redeploy neither reinstalls nor restarts"
update_file.py my_test_code/__main__.py "Hello from my func" "Hello from my func v2"
$CLI bundle deploy &> LOG.redeploy
# The libraries path is unchanged, so the plan sees no library change: the cluster is
# not restarted and no install request is issued, leaving the stale wheel running. The
# following two assertions encode that known limitation (see the TODO in cluster.go).
cat LOG.redeploy | contains.py "!Restarting cluster" > /dev/null
printf '\n%s\n' "OK: no restart on content-only change (known limitation)"
trace print_requests.py //libraries/install
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
uv venv -q .venv
venv_activate
uv pip install -q --no-index setuptools
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from setuptools import setup, find_packages

import my_test_code

setup(
name="my_test_code",
version=my_test_code.__version__,
author=my_test_code.__author__,
url="https://databricks.com",
author_email="john.doe@databricks.com",
description="my example wheel",
packages=find_packages(include=["my_test_code"]),
entry_points={"group1": "run=my_test_code.__main__:main"},
install_requires=["setuptools"],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Badness = "A local wheel whose contents change but whose version (and thus workspace path) does not is not detected in non-dev mode, so redeploy neither reinstalls it nor restarts the cluster; the stale wheel keeps running. See the TODO in bundle/direct/dresources/cluster.go DoUpdate."

Cloud = true
CloudSlow = true
RecordRequests = true

EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"]

Ignore = [".databricks", ".venv", "build", "dist", "my_test_code.egg-info", "databricks.yml"]

[[Repls]]
Old = "[0-9]{4}-[0-9]{6}-[0-9a-z]{8}"
New = "[UUID]"
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
bundle:
name: libraries-readplan-not-uploaded

resources:
clusters:
mycluster:
cluster_name: mycluster
spark_version: 15.4.x-scala2.12
node_type_id: Standard_DS3_v2
num_workers: 1
libraries:
# Prebuilt local wheel (no build: step) to keep the test hermetic.
- whl: ./dist/*.whl
Binary file not shown.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

>>> [CLI] bundle plan -o json

>>> [CLI] bundle deploy --plan tmp.plan.json
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/libraries-readplan-not-uploaded/default/files...
Created clusters.mycluster
Files: 6 uploaded, 0 deleted
Resources: 1 created, 0 changed, 0 deleted, 0 unchanged

>>> [CLI] bundle destroy --auto-approve
The following resources will be deleted:
delete resources.clusters.mycluster

All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/libraries-readplan-not-uploaded/default

Destroy: 1 deleted
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# A cluster's local wheel library is uploaded by `bundle deploy` but NOT by
# `bundle deploy --plan`. This tripwire pins that difference.
# Can be removed once fixed, and other tests can be moved to READPLAN variants.
#See acceptance/bundle/deploy/readplan/whl-not-uploaded for the bug.
trace $CLI bundle plan -o json > tmp.plan.json
trace $CLI bundle deploy --plan tmp.plan.json
trace $CLI bundle destroy --auto-approve
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Badness = "bundle deploy --plan skips the build phase, so a cluster's local wheel is never uploaded (proven in deploy/readplan/whl-not-uploaded). Kept as a note: when the bug is fixed, deploy --plan will print 'Uploading dist/...' and this golden changes - then delete this test and restore EnvMatrix.READPLAN = [\"\", \"1\"] on clusters/libraries and clusters/libraries-content-change."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't we already have a test for this?

@Sankalp-Mittal Sankalp-Mittal Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this here as a reminder that once that issue is fixed READPLAN variants are added for tests here

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we land the fix for build with --plan first? might affect the design here.


EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"]
# This test is just asserting bad behaviour so that it can be removed once that behaviour is fixed
RecordRequests = false
Ignore = [".databricks", "tmp.plan.json"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
bundle:
name: cluster-libraries-repo-$UNIQUE_NAME

workspace:
root_path: ~/.bundle/$UNIQUE_NAME

resources:
clusters:
mycluster:
cluster_name: mycluster-$UNIQUE_NAME
spark_version: $DEFAULT_SPARK_VERSION
node_type_id: $NODE_TYPE_ID
instance_pool_id: $TEST_INSTANCE_POOL_ID
num_workers: 1
libraries:
- pypi:
package: requests
repo: https://pypi.org/simple

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions acceptance/bundle/resources/clusters/libraries-repo/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

=== Deploy creates the cluster and installs the pypi library
OK: cluster created with pypi library

=== Plan is a no-op after deploy: the repo round-trips
>>> [CLI] bundle plan
Plan: 0 to add, 0 to change, 0 to delete, 1 unchanged

=== Changing only the repo is planned as an update
>>> [CLI] bundle plan
update clusters.mycluster

Plan: 0 to add, 1 to change, 0 to delete, 0 unchanged

>>> [CLI] bundle destroy --auto-approve
The following resources will be deleted:
delete resources.clusters.mycluster

All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]

Destroy: 1 deleted
21 changes: 21 additions & 0 deletions acceptance/bundle/resources/clusters/libraries-repo/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
envsubst < databricks.yml.tmpl > databricks.yml

cleanup() {
trace $CLI bundle destroy --auto-approve
rm -f out.requests.txt
}
trap cleanup EXIT

# Deploy output goes to LOG (differs fake vs cloud); echo a pass line instead.
title "Deploy creates the cluster and installs the pypi library"
$CLI bundle plan -o json > tmp.plan.json 2>>LOG.plan
$CLI bundle deploy $(readplanarg tmp.plan.json) &> LOG.deploy
cat LOG.deploy | contains.py "Created clusters.mycluster" > /dev/null
printf '\n%s\n' "OK: cluster created with pypi library"

title "Plan is a no-op after deploy: the repo round-trips"
trace $CLI bundle plan

title "Changing only the repo is planned as an update"
Comment thread
andrewnester marked this conversation as resolved.
update_file.py databricks.yml "repo: https://pypi.org/simple" "repo: https://example.invalid/simple"
trace $CLI bundle plan
12 changes: 12 additions & 0 deletions acceptance/bundle/resources/clusters/libraries-repo/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Cloud = true
CloudSlow = true
RecordRequests = false

EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"]
EnvMatrix.READPLAN = ["", "1"]

Ignore = [".databricks", "databricks.yml", "tmp.plan.json"]

[[Repls]]
Old = "[0-9]{4}-[0-9]{6}-[0-9a-z]{8}"
New = "[UUID]"
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
bundle:
name: cluster-libraries-restart-$UNIQUE_NAME

workspace:
root_path: ~/.bundle/$UNIQUE_NAME

resources:
clusters:
mycluster:
cluster_name: mycluster-$UNIQUE_NAME
spark_version: $DEFAULT_SPARK_VERSION
node_type_id: $NODE_TYPE_ID
instance_pool_id: $TEST_INSTANCE_POOL_ID
num_workers: 1
libraries:
- pypi:
package: requests

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading