Skip to content

Add app_spaces as a DABs resource type (direct mode only)#4982

Open
bernardo-rodriguez wants to merge 12 commits intodatabricks:mainfrom
bernardo-rodriguez:add-app-spaces-dabs-resource
Open

Add app_spaces as a DABs resource type (direct mode only)#4982
bernardo-rodriguez wants to merge 12 commits intodatabricks:mainfrom
bernardo-rodriguez:add-app-spaces-dabs-resource

Conversation

@bernardo-rodriguez
Copy link
Copy Markdown

@bernardo-rodriguez bernardo-rodriguez commented Apr 16, 2026

Changes

Adds support for declaring Databricks App Spaces in bundle YAML via the app_spaces resource type. Spaces are containers for apps that provide shared resources, OAuth scopes, and a service principal.

Implements direct mode CRUD with async operation waiting, a merge mutator for the space resources array, run_as validation, and test server handlers for the fake workspace.

Why

App spaces are are in private preview, we want to add support for the developer ecosystem.

Tests

Tested with local CLI build.

Test databricks.yml file:

resources:
  app_spaces:
    space_with_resources:
      name: test-space-with-resources
      description: "A space with shared resources"
      resources:
        - name: my-serving-endpoint
          serving_endpoint:
            name: databricks-meta-llama-3-3-70b-instruct
            permission: CAN_QUERY
        - name: my-warehouse                                                                                                        
          sql_warehouse:                                                                                                            
            id: 668e77c7ff1fce2d                          
            permission: CAN_USE
  apps:
    my_app:
      name: app-in-space
      space: ${resources.app_spaces.space_with_resources.name}
      source_code_path: ./my-app
      lifecycle:                                                                                                                    
        started: true
      config:
        command:
          - python
          - app.py
        env:
          - name: APP_ENV
            value: staging

Commands:

DATABRICKS_BUNDLE_ENGINE=direct ../cli/databricks bundle deploy
Uploading bundle files to /Workspace/Users/bernardo.rodriguez@databricks.com/.bundle/test-app-spaces/dev/files...
Deploying resources...
Updating deployment state...
Deployment complete!

New app space:

databricks apps get-space test-space-with-resources
{
  "create_time":"2026-04-16T01:40:18Z",
  "creator":"bernardo.rodriguez@databricks.com",
  "description":"A space with shared resources",
  "name":"test-space-with-resources",
  "resources": [
    {
      "name":"my-serving-endpoint",
      "serving_endpoint": {
        "name":"databricks-meta-llama-3-3-70b-instruct",
        "permission":"CAN_QUERY"
      }
    },
    {
      "name":"my-warehouse",
      "sql_warehouse": {
        "id":"668e77c7ff1fce2d",
        "permission":"CAN_USE"
      }
    }
  ],
  "status": {
    "message":"Space is ready.",
    "state":"SPACE_ACTIVE"
  },
  ...
}

New App:

databricks apps get app-in-space
{
  "app_status": {
    "message":"App has status: App has not been deployed yet. Run your app by deploying source code",
    "state":"UNAVAILABLE"
  },
  "compute_size":"LIQUID",
  "compute_status": {
    "message":"App compute is running.",
    "state":"ACTIVE"
  },
  "create_time":"2026-04-16T01:40:25Z",
  "creator":"bernardo.rodriguez@databricks.com",
  "description":"",
  "effective_user_api_scopes": [
    "iam.current-user:read",
    "iam.access-control:read"
  ],
  "name":"app-in-space",
  "space":"test-space-with-resources",
  "update_time":"2026-04-16T01:41:22Z",
  "updater":"bernardo.rodriguez@databricks.com",
  "url":"https://app-in-space-4119111590058294.0.staging.azure.databricksapps.com",
   ....
}
  • Test updating the app spaces with new resource and running bundle deploy makes desired updates
  • Test removing the app spaces from the yml file and deploying deletes the app spaces
  • Test bundle destroy deletes the app spaces
  • Unit tests

Copy link
Copy Markdown
Contributor

@andrewnester andrewnester left a comment

Choose a reason for hiding this comment

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

Could you please add acceptance test for the new resource, see for example

https://github.com/databricks/cli/tree/main/acceptance/bundle/resources/apps/update

Comment thread bundle/direct/dresources/app_space.go
Comment thread bundle/config/mutator/resourcemutator/merge_app_spaces.go Outdated
Comment thread bundle/direct/dresources/resources.yml
_, err := r.client.Apps.UpdateSpace(ctx, apps.UpdateSpaceRequest{
Name: id,
Space: *config,
UpdateMask: fieldmask.FieldMask{Paths: []string{"description", "resources", "user_api_scopes", "usage_policy_id"}},
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.

Static list is fine, but I'm curious, is * not working for this endpoint?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

no, the server explicitly allowlists fields, using * fails with a server side validation error

@@ -0,0 +1,17 @@
bundle:
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.

Please look into adding invariant tests as well - you need one config in acceptance/bundle/invariant/configs.

Does this resource support permissions?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes, thanks for calling this out!

App Spaces support 3 different permissions levels (CAN_USE, CAN_CREATE, CAN_MANAGE) via /api/2.0/permissions/app-spaces/{space-name}. I added a new AppSpacePermission type to handle this.

Also, added that invariant config.

Comment thread acceptance/bundle/resources/app_spaces/basic/script Outdated
Copy link
Copy Markdown
Contributor

@janniklasrose janniklasrose left a comment

Choose a reason for hiding this comment

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

Please address:

  • test failures
  • auto-gen relevant files
  • add additional acceptance tests (definitely invariant, drift, also bind/unbind if relevant)
  • opt out of terraform in bundle/config/mutator/validate_direct_only_resources.go
  • add entry to NEXT_CHANGELOG.md

Comment on lines +18 to +23
title "Update name and re-deploy"
trace update_file.py databricks.yml myspacename mynewspacename
trace $CLI bundle plan
trace $CLI bundle summary
trace $CLI bundle deploy
trace print_requests >> out.requests.$DATABRICKS_BUNDLE_ENGINE.json
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: same as recreate

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

true. leaving for now as they have a different event sequence, but I can remove the rename state from the update test if you prefer a cleaner separation

Comment on lines +18 to +27
>>> [CLI] bundle plan
recreate app_spaces.mykey

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

>>> [CLI] bundle deploy
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files...
Deploying resources...
Updating deployment state...
Deployment complete!
Copy link
Copy Markdown
Contributor

@janniklasrose janniklasrose Apr 21, 2026

Choose a reason for hiding this comment

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

just confirming that recreating app_spaces is safe (no data loss)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yea that is fine, they are just metadata and store no customer data

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.

What happens if you delete an app space that has >0 apps attached?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@pietern the server blocks deletion with 400 BAD_REQUEST: Cannot delete space <name> because it contains N app

Comment thread bundle/config/resources/app_spaces.go Outdated
Comment thread bundle/config/resources/app_spaces.go Outdated
Comment thread bundle/config/resources/app_spaces.go
Comment thread bundle/direct/dresources/app_space.go Outdated
func (r *ResourceAppSpace) DoCreate(ctx context.Context, config *apps.Space) (string, *apps.Space, error) {
// Kick off the create request. Wait for the space to become active in
// WaitAfterCreate so that parallel creates are not blocked here.
_, err := r.client.Apps.CreateSpace(ctx, apps.CreateSpaceRequest{
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 not modeled after a long running operation?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

yes, I updated to match other examples of LRO, by using the waiter returned by the Create and Update method.

Comment on lines +18 to +27
>>> [CLI] bundle plan
recreate app_spaces.mykey

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

>>> [CLI] bundle deploy
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files...
Deploying resources...
Updating deployment state...
Deployment complete!
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.

What happens if you delete an app space that has >0 apps attached?

bernardo-rodriguez and others added 9 commits April 22, 2026 08:11
Adds support for declaring Databricks App Spaces in bundle YAML via
the `app_spaces` resource type. Spaces are containers for apps that
provide shared resources, OAuth scopes, and a service principal.

Implements direct mode CRUD with async operation waiting, a merge
mutator for the space resources array, run_as validation, and test
server handlers for the fake workspace.

Co-authored-by: Isaac
The Spaces API rejects wildcard update masks. Use the explicit list
of updatable fields: description, resources, user_api_scopes,
usage_policy_id.

Co-authored-by: Isaac
- Add nolint comment for Id field collision between BaseResource and
  apps.Space (same pattern as App resource)
- Regenerate annotations.yml and jsonschema.json via make schema
- Add acceptance tests: basic (with nested resources), recreate (name
  immutability), update (create/update/rename/destroy lifecycle)

Co-authored-by: Isaac
Previous golden files were generated with Python 3.6 which doesn't
support f-string self-documenting expressions used in update_file.py,
causing bogus SyntaxError output that would fail in CI.

Co-authored-by: Isaac
Previously DoCreate and DoUpdate blocked on waiter.Wait, preventing
the direct engine from parallelizing operations across resources.
Move the wait into dedicated WaitAfterCreate/WaitAfterUpdate methods
that poll GetSpace until the space reaches SPACE_ACTIVE state.

Addresses review feedback from @andrewnester.

Co-authored-by: Isaac
- Scope govet lint directive to a specific linter (Jannik)
- Remove fabricated InitializeURL; spaces have no stable UI URL yet (Jannik)
- Opt out of terraform via ValidateDirectOnlyResources (Jannik)
- Replace panic in merge_app_spaces with user-facing diagnostic (Denik)
- Add permissions support for app_spaces using the generic
  /api/2.0/permissions/app-spaces/{name} endpoint
- Use print_requests.py helper in acceptance scripts (Denik)
- Add invariant, drift (via invariant no_drift), and bind/unbind
  acceptance tests (Jannik)
- Exclude app_space from migrate invariant test since the resource is
  direct-only (same pattern as catalog, external_location)
- Regenerate annotations, jsonschema, enum_fields, required_fields
- Fix TestConvertLifecycleForAllResources and state_load tests to
  account for the new resource
- Add NEXT_CHANGELOG.md entry

Note: resources.generated.yml needs make generate-direct to populate
output-only fields (create_time, service_principal_*, status, etc.)
from the OpenAPI spec. Until then, invariant no_drift for app_space
will fail locally; CI pipelines with VPN access will keep it in sync.

Co-authored-by: Isaac
- NEXT_CHANGELOG.md: remove bullets for databricks#4672 and databricks#4941 that were
  accidentally re-added during a stash/pop across a v0.297 release cut
- acceptance/bundle/invariant/{continue_293,migrate,no_drift}/out.test.toml:
  restore job_with_depends_on.yml.tmpl that got dropped during a
  merge-conflict resolution on an earlier rebase

Co-authored-by: Isaac
@bernardo-rodriguez bernardo-rodriguez force-pushed the add-app-spaces-dabs-resource branch from 9823c27 to e8ce30b Compare April 22, 2026 12:13
@github-actions
Copy link
Copy Markdown

An authorized user can trigger integration tests manually by following the instructions below:

Trigger:
go/deco-tests-run/cli

Inputs:

  • PR number: 4982
  • Commit SHA: dd092e04a68df4e05efd1022ea07835f3a26591d

Checks will be approved automatically on success.

@andrewnester andrewnester self-requested a review April 22, 2026 16:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants