Skip to content

Add libraries field to the clusters resource - #6365

Open
Sankalp-Mittal wants to merge 47 commits into
mainfrom
sankalp-mittal/all-purpose-cluster-libraries
Open

Add libraries field to the clusters resource#6365
Sankalp-Mittal wants to merge 47 commits into
mainfrom
sankalp-mittal/all-purpose-cluster-libraries

Conversation

@Sankalp-Mittal

@Sankalp-Mittal Sankalp-Mittal commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Changes

Add support for installing libraries on all-purpose clusters. Libraries are declared as a field of the cluster resource, not a separate resource:

resources:
  clusters:
    my_cluster:
      cluster_name: my-cluster
      spark_version: 15.4.x-scala2.12
      node_type_id: i3.xlarge
      num_workers: 1
      libraries:
        - pypi:
            package: requests
        - whl: ./dist/*.whl

A cluster's libraries are not part of the cluster create/edit spec, so they are managed through the dedicated Libraries API (install, uninstall, cluster-status) as part of the cluster lifecycle. Installed libraries are read back via cluster-status, so library changes participate in normal drift detection. Local .whl artifacts are built, uploaded, and rewritten to their workspace path before install.

Install/uninstall cases:

  • Create — libraries install on the freshly started cluster; no restart is needed (a new cluster has no active sessions).
  • Add or change a library — the desired set is installed and any removed libraries uninstalled. A running cluster is restarted so the change takes effect; a stopped cluster applies it on its next start.
  • Remove all libraries — the libraries are uninstalled, restarting a running cluster.

Why

Resolves #1860.

Tests

Acceptance tests covering create / add / remove, local wheel build-and-upload, repo-hosted wheels, and the stopped-cluster (no restart) case. They run locally against the fake server and additionally against a real workspace (Cloud = true).

Also manually verified on a real Azure workspace: a job with a python_wheel_task and no task-level library successfully ran a wheel installed only via the cluster's libraries: field, confirming a cluster-installed library is actually usable by workloads.

@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 612add7

Run: 33055410181

Env 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
💚​ aws linux 2 3 287 1486 12:46
💚​ aws windows 2 3 289 1484 11:08
💚​ azure linux 2 3 286 1486 11:29
💚​ azure windows 2 3 288 1484 10:26
💚​ gcp linux 2 3 287 1486 17:48
💚​ gcp windows 2 3 289 1484 15:16
Test Name aws linux aws windows azure linux azure windows gcp linux gcp windows
💚​ TestAccept 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
💚​ TestAccept/bundle/invariant/no_drift 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
🙈​ TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_indexes/recreate/embedding_dimension 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/ssh/connection 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
Top 45 slowest tests (at least 2 minutes):
duration env testname
8:41 gcp windows TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
8:32 gcp windows TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
8:18 gcp linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
8:10 gcp linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
8:00 gcp windows TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
7:58 gcp linux TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
7:52 gcp linux TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
7:49 gcp linux TestAccept/bundle/resources/clusters/libraries-drift/DATABRICKS_BUNDLE_ENGINE=direct
7:28 azure linux TestAccept/bundle/resources/clusters/libraries-drift/DATABRICKS_BUNDLE_ENGINE=direct
7:26 aws linux TestAccept/bundle/resources/clusters/libraries-drift/DATABRICKS_BUNDLE_ENGINE=direct
7:23 aws linux TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
7:19 aws linux TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
7:15 azure linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
7:11 azure linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
7:10 aws windows TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
7:09 aws linux TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
6:58 aws windows TestAccept/bundle/resources/clusters/libraries-drift/DATABRICKS_BUNDLE_ENGINE=direct
6:48 azure linux TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
4:27 azure windows TestAccept
4:20 gcp windows TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
4:17 gcp windows TestAccept/bundle/resources/clusters/libraries-drift/DATABRICKS_BUNDLE_ENGINE=direct
3:47 gcp linux TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
3:37 aws linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
3:29 aws windows TestAccept
3:25 aws linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
3:25 gcp windows TestAccept
3:20 gcp windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
3:16 azure windows TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
3:08 azure windows TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
3:02 gcp windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
3:01 gcp linux TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
2:44 azure windows TestAccept/bundle/resources/clusters/libraries-drift/DATABRICKS_BUNDLE_ENGINE=direct
2:38 azure windows TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
2:37 aws windows TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
2:35 aws linux TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
2:34 azure linux TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
2:33 aws windows TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
2:33 azure windows TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
2:24 azure windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
2:24 azure windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
2:20 aws windows TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
2:18 aws windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
2:11 aws windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
2:11 azure linux TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
2:08 azure linux TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1

@Sankalp-Mittal
Sankalp-Mittal force-pushed the sankalp-mittal/all-purpose-cluster-libraries branch from e378a6a to e4e688e Compare August 25, 2026 09:36
@Sankalp-Mittal Sankalp-Mittal changed the title add libraries field for Clusters Add libraries field to the clusters resource Aug 26, 2026
@Sankalp-Mittal
Sankalp-Mittal marked this pull request as ready for review August 26, 2026 08:19
@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Approval status: pending

/acceptance/bundle/ - needs approval

46 files changed
Suggested: @denik
Also eligible: @pietern, @janniklasrose, @andrewnester, @shreyas-goenka, @anton-107, @lennartkats-db

/bundle/ - needs approval

12 files changed
Suggested: @denik
Also eligible: @pietern, @janniklasrose, @andrewnester, @shreyas-goenka, @anton-107, @lennartkats-db

General files (require maintainer)

5 files changed
Based on git history:

  • @denik -- recent work in libs/testserver/, .nextchanges/bundles/, bundle/config/mutator/

Any maintainer (@andrewnester, @anton-107, @denik, @pietern, @shreyas-goenka, @simonfaltum, @renaudhartert-db, @janniklasrose, @lennartkats-db, @rugpanov, @rclarey) can approve all areas.
See OWNERS for ownership rules.

@Sankalp-Mittal

Copy link
Copy Markdown
Collaborator Author

Check if a library is changes and all others are unchanged, does only reinstalling the change library work or can others have a dependency on it and everything needs to be reinstalled

Comment thread bundle/direct/dresources/cluster_libraries.go Outdated
Comment thread acceptance/bundle/invariant/continue_293/out.test.toml Outdated
Comment thread acceptance/bundle/refschema/out.fields.txt Outdated
Comment thread acceptance/bundle/resources/clusters/libraries-drift/script Outdated
Comment thread acceptance/bundle/resources/clusters/libraries/out.test.toml Outdated
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/cluster-libraries/default/files...
Updated clusters.mycluster.libraries
Files: 3 uploaded, 0 deleted
Resources: 0 created, 1 changed, 0 deleted, 1 unchanged

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.

nit: Should we mark it deleted instead of changed?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

this actually counts as an update to the libraries resource, hence marked as changed, delete is only when the entire node is removed

Comment thread bundle/config/resources_types.go Outdated
Comment thread bundle/direct/dresources/cluster_libraries.go Outdated
Comment thread bundle/direct/dresources/cluster_libraries.go Outdated
Comment thread bundle/direct/dresources/cluster_libraries.go Outdated
@@ -34,6 +35,9 @@ package terraform_dabs_map
// TerraformToDABsFieldMap maps DABs group name → nested TF segments → DABs segment name.
// Navigate using TF field name segments; DABs is the corresponding DABs name when it differs.
var TerraformToDABsFieldMap = map[string]RenameTree{

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.

If this is direct only change, why is this changed?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Apparently terraform always had a library block, it was just never supported in DABs, which now causes this file to register a rename to libraries. Terraform is explicitly blocked in validate_cluster_libraries.go. I don't think terraform should be supported since we have moved to direct only

Sankalp-Mittal and others added 14 commits August 27, 2026 10:44
Wire the direct engine to treat resources.clusters.*.libraries as a
child-resource node, the same way permissions and grants are handled:
node/type resolution, reference splitting, and plan node discovery.

Co-authored-by: Isaac <no-reply@databricks.com>
Implement ResourceLibraries: installs/uninstalls cluster libraries via
the Libraries API, reconciling removed libraries on update and polling
for install completion on a running cluster. Registered in all.go.

Note: TestAll/clusters.libraries fails until the testserver models the
libraries install/uninstall/cluster-status endpoints (next step).

Co-authored-by: Isaac <no-reply@databricks.com>
Add stateful fakes for the Libraries API (install, uninstall,
cluster-status) so clusters.libraries runs against the in-process
server. Add the TestAll fixture and classify libraries as a no-op
delete alongside permissions/grants; this greens TestAll/clusters.libraries.

Co-authored-by: Isaac <no-reply@databricks.com>
Add clusterLibrariesPattern (resources.clusters.*.libraries) to glob
expansion, local-library collection/upload, duplicate-name checking,
and patched-wheel swapping, mirroring the job task library wiring. Local
whl/jar globs now build, upload to artifact_path/.internal, and rewrite
to absolute workspace paths; pypi/maven entries pass through unchanged.

Co-authored-by: Isaac <no-reply@databricks.com>
Add ValidateClusterLibraries and register it in PreDeployChecks so a
libraries block on a cluster errors under the terraform engine instead
of being silently dropped. Cluster libraries are direct-only. Mirrors
the existing lifecycle.started guard.

Co-authored-by: Isaac <no-reply@databricks.com>
Adding the clusters libraries field makes DABs libraries map to the
terraform databricks_cluster.library field; regenerate the mapping so
reference translation and the tf-only field audit stay correct.

Co-authored-by: Isaac <no-reply@databricks.com>
- clusters/libraries: direct-engine deploy installs pypi + local wheel
  (rewritten to its uploaded path), and removing the wheel and
  redeploying uninstalls it.
- clusters/libraries-terraform-error: bundle plan/deploy reject cluster
  libraries under the terraform engine.

Co-authored-by: Isaac <no-reply@databricks.com>
Enumerate the remaining LibraryInstallStatus cases in the install-wait
poll and set EmbeddedSlice explicitly in DoRead's state literal.

Co-authored-by: Isaac <no-reply@databricks.com>
clusters/libraries-drift (Cloud = true, direct engine): deploy a cluster
with a pypi library, then assert the immediate re-plan is a no-op
(0 to change). Verified on a real AWS workspace: the Libraries status API
round-trips the library without drift, so no normalization is needed.

Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
Pipelines have a native libraries field that is a plain field, not a
child resource. The sub-resource wiring matched resources.*.*.libraries
for every resource type, so the direct engine tried to plan
pipelines.libraries as a resource and failed with 'unsupported resource
type: pipelines.libraries'. Scope both GetNodeAndType and the plan
pattern to clusters.

Co-authored-by: Isaac <no-reply@databricks.com>
Consistency follow-up to the GetNodeAndType/plan-pattern scoping:
ResourcesTypes registered a .libraries key for every resource type with
a Libraries field, spuriously adding pipelines.libraries and
cluster_policies.libraries. Those keys are unreachable now that
GetNodeAndType is scoped, but scope this branch too so the map stays
consistent and the entries don't mislead future callers.

Co-authored-by: Isaac <no-reply@databricks.com>
Two CI failures in the local acceptance suite:

1. bundle/resources/clusters/libraries deployed a prebuilt wheel from
   ./dist/*.whl, but dist/ is gitignored so the fixture was never
   committed. CI's clean checkout hit 'no files match pattern:
   ./dist/*.whl'. Force-add the dummy wheel as a committed test input.

2. TestInvariantConfigsCoverage requires every config.ResourcesTypes key
   to be covered. clusters.libraries had no coverage: the scanner only
   understood .permissions/.grants sub-resources. Teach it .libraries
   too, add a pypi-only cluster_libraries invariant config, and wire it
   into INPUT_CONFIG. Cluster libraries are direct-only, so exclude the
   config from the terraform-seeded migrate subtest like the other
   direct-only resources.

Co-authored-by: Isaac <no-reply@databricks.com>
@Sankalp-Mittal
Sankalp-Mittal force-pushed the sankalp-mittal/all-purpose-cluster-libraries branch from 6b15637 to 612add7 Compare August 27, 2026 08:44
Sankalp-Mittal and others added 7 commits August 31, 2026 11:34
Installs are invisible to attached notebooks and uninstalls are deferred until restart, so restart the running cluster after a library change (WaitAfterUpdate/WaitAfterDelete). DoDelete now uninstalls recorded libraries.

Co-authored-by: Isaac <no-reply@databricks.com>
Cover full-block removal (Delete path: uninstall + restart) and a stopped cluster (restart skipped when the cluster is not running).

Co-authored-by: Isaac <no-reply@databricks.com>
Set all fields (RestartUser, ForceSendFields) explicitly, matching the dresources exhaustruct convention.

Co-authored-by: Isaac <no-reply@databricks.com>
The broad //libraries filter degrades to a bare 'libraries' substring on
Windows Git Bash, matching the bundle name (cluster-libraries-stopped) in
file-upload paths and dumping unrelated requests. Use //libraries/install
like the sibling tests so the filter stays specific across platforms.

Co-authored-by: Isaac <no-reply@databricks.com>
Sankalp-Mittal and others added 19 commits August 31, 2026 12:31
Cluster libraries postdate v0.293.0, so the old CLI cannot deploy the config; exclude it like the other post-0.293 resources. Addresses PR review feedback.

Co-authored-by: Isaac <no-reply@databricks.com>
splitResourcePath treated any 4th-component 'libraries' as a sub-resource, but only clusters expose libraries as one; pipelines have a native top-level libraries field, so a reference into a pipeline's libraries mis-split to a non-existent node. Scope it to clusters, matching makePlan. Addresses Isaac Review finding.

Co-authored-by: Isaac <no-reply@databricks.com>
libraryKey ignored pypi/maven/cran repo and maven exclusions, so a change to only the repo was treated as no change and never applied. The backend hashes these into library_id_hash and round-trips them on cluster-status, so include them. Adds a Cloud=true test covering repo round-trip + repo-change detection.

Co-authored-by: Isaac <no-reply@databricks.com>
The libraries sub-resource is emitted by both the clusters adapter's input
walk (as an INPUT-only block) and the clusters.libraries sub-resource adapter
(as an ALL block), duplicating resources.clusters.*.libraries in the refschema
dump. permissions and grants avoid this via an explicit skip filter; extend it
to libraries, scoped to clusters since pipelines have a native top-level
libraries field.

Co-authored-by: Isaac <no-reply@databricks.com>
The invariant no_drift suite now runs configs/cluster_libraries.yml.tmpl (added
in 612add7), which deploys the identical pypi-requests cluster config and
asserts no drift after deploy, plus the delete/destroy/migrate idempotency
variants. That makes the standalone libraries-drift cloud test a strict subset.
The restart-on-destroy output it captured is already asserted in the local
libraries test, and libraries-repo remains as the stronger repo round-trip check.

Co-authored-by: Isaac <no-reply@databricks.com>
The three pypi/wheel tests were authored fake-only (hardcoded i3.xlarge, no
$UNIQUE_NAME, no instance pool, static databricks.yml), so they could not run
against a real workspace. Convert them to cloud:

- libraries: build a real wheel via setup.py + an artifacts block (mirroring
  integration_whl/interactive_cluster) instead of the 20-byte dummy stub, so
  the /Workspace wheel install is exercised on a real cluster. Cloud + CloudSlow;
  data_security_mode=USER_ISOLATION. Deploy output routed to LOG; asserts the
  install request (rewritten /Workspace wheel path), uninstall, and restart.
- libraries-remove-all, libraries-stopped-cluster: parameterize databricks.yml
  as a .tmpl with cloud vars and instance pool; assert summary/restart lines
  instead of exact request bodies (which the recording proxy makes redundant).
- All four tests: map the cloud cluster-id format to [UUID] so cloud output
  matches the fake run.

All four remain Cloud=true and still run locally against the fake server.

Co-authored-by: Isaac <no-reply@databricks.com>
The Aug 27 DABs core-eng meeting finalized that cluster libraries are managed
as part of the cluster resource (Option 3), not as a `clusters.libraries`
sub-resource. This reworks the feature accordingly:

- Fold install/uninstall/restart into ResourceCluster: Libraries is now a field
  of ClusterState and ClusterRemote (DoRead populates it from the Libraries
  cluster-status API). WaitAfterCreate installs on the freshly-running cluster;
  DoUpdate reconciles (uninstall removed + install desired) and restarts a
  running cluster so the change takes effect (a cluster edit already restarts,
  so we only restart ourselves when no edit fired). KeyedSlices keys libraries
  by identity so reordering is not drift.
- Delete cluster_libraries.go and remove all sub-resource wiring (all.go,
  resources_types.go, root.go, bundle_plan.go splitResourcePath + makePlan,
  refschema.go skip). Library changes now surface as `update clusters.<name>`,
  and destroy no longer wastefully restarts (PermanentDelete removes the cluster).
- Rewrite the clusters/libraries* acceptance tests and regenerate refschema for
  the part-of-cluster shape.

Co-authored-by: Isaac <no-reply@databricks.com>
A local whl/jar whose workspace path is unchanged but whose contents changed
(same name+version, non-dev mode) does not trigger a restart. Note the gap and
why hashing the built wheel is unsafe (non-reproducible zip mtimes); a general
fix needs a source hash in state.

Co-authored-by: Isaac <no-reply@databricks.com>
Add clusters/libraries-restart (Cloud=true, pypi-only) pinning restart behaviour
across the library lifecycle on a single cluster:
- install (create): libraries install on the fresh cluster with NO restart
- update (add a library): the running cluster is restarted
- delete (remove all libraries): the running cluster is restarted

Fold in clusters/libraries-remove-all, whose remove-all -> restart case is
subsumed by the delete step here, keeping the Cloud=true cluster count flat.

Co-authored-by: Isaac <no-reply@databricks.com>
…inue

Regenerate the cluster-libraries acceptance snapshots to carry
EnvMatrix.DMS = ["", "true"] after merging main's DMS test matrix, fixing
the post-test git-diff drift check. Also remove the now-dead continue at the
end of the Grants loop body in resources_types.go, orphaned when the Libraries
block was removed in the part-of-cluster rewrite.

Co-authored-by: Isaac <no-reply@databricks.com>
In the part-of-cluster model libraries is a field of ClusterState, not a
sub-resource, so there is no clusters.libraries key in config.ResourcesTypes
and no resource with top-level libraries missing in state. Drop the now-dead
".libraries" scanning in the invariant coverage test and the "libraries" entry
in commonMissingInStateType.

Co-authored-by: Isaac <no-reply@databricks.com>
The initial deploy step routed its output to LOG and asserted signals via
contains.py, but had no title, so the phase was invisible in output.txt. Add a
title so the golden documents it, matching the other cluster-libraries tests.

Co-authored-by: Isaac <no-reply@databricks.com>
Comment thread .nextchanges/bundles/cluster-libraries.md Outdated
)

// librariesWaitTimeout bounds how long we poll for libraries to finish installing.
const librariesWaitTimeout = 15 * time.Minute

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.

Is this chosen to match terraform? What happens when time runs out?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

this was just taken to be half of clusterWaitTimeout, I was not really sure what to keep it, if the timer runs out the deploy fails

Comment thread bundle/direct/dresources/cluster.go Outdated
Comment thread bundle/direct/dresources/cluster.go Outdated
Comment thread bundle/direct/dresources/cluster.go
trap cleanup EXIT

# Deploy output is noisy and differs fake vs cloud; assert only the plan signals below.
$CLI bundle deploy &> LOG.deploy

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.

could you add READPLAN variant to these tests?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

done

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

There is an issue where the READPLAN variant doesn't work #6490

Comment thread bundle/direct/dresources/cluster.go
Sankalp-Mittal and others added 6 commits September 1, 2026 15:02
Run each cluster-libraries test through a saved plan (bundle plan -o json,
applied via readplanarg) in addition to the inline deploy, mirroring
clusters/readplan-lifecycle. Addresses review feedback. Deploy and plan output
route to LOG/tmp.plan.json, so output.txt is unchanged; only the READPLAN
matrix is added.

Co-authored-by: Isaac <no-reply@databricks.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: configure all-purpose cluster libraries through DAB

4 participants