From 222eaa47f4b38f272cc6692b3b0fb8cd357eda0d Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Mon, 31 Aug 2026 11:27:33 +0000 Subject: [PATCH 01/22] Bump databricks-sdk-go from v0.175.0 to v0.177.0 ## Changes Bump `github.com/databricks/databricks-sdk-go` from v0.175.0 to v0.177.0 and the pinned OpenAPI spec SHA to `0f2c9a3d`. Regenerated all downstream artifacts from the new spec: CLI command stubs, bundle JSON schema, validation, direct-engine resources, pydabs models, and the DABs<->TF field map. User-visible additions include the jobs continuous `maintenance_window` field and the pipelines RabbitMQ connector options; the postgres branch `source_snapshot` field is now handled as immutable/input-only by the direct engine. The v0.177.0 `ml.*` field removals (feature-engineering) are not referenced by hand-written CLI code, so they required no source changes. The SDK now marks the pipelines `continuous` field deprecated; it remains a supported bundle config field, so its four usages carry `//nolint:staticcheck` (SA1019). ## Why Keep the CLI current with the latest SDK and provide a clean base for upcoming feature work. ## Tests Acceptance goldens regenerated via `-update` (help text + refschema). The non-update verify pass is green apart from load-induced terraform-engine timeout flakes, each confirmed passing in isolation. Root-module unit suite passes (9532 tests). `./task fmt`, `./task lint`, and `./task checks` clean. Co-authored-by: Isaac --- .codegen/_openapi_sha | 2 +- .codegen/cli.json | 4993 ++++++++++++----- .../dependency-updates/bump-sdk-0.177.0.md | 1 + acceptance/bundle/refschema/out.fields.txt | 29 + .../cmd/account/account-help/output.txt | 2 +- acceptance/help/output.txt | 4 +- .../mutator/resourcemutator/apply_presets.go | 1 + .../resourcemutator/apply_target_mode_test.go | 2 +- bundle/direct/dresources/pipeline.go | 4 +- .../direct/dresources/resources.generated.yml | 4 + .../validation/generated/enum_fields.go | 8 +- .../validation/generated/required_fields.go | 8 +- bundle/schema/jsonschema.json | 166 +- bundle/terraform_dabs_map/generated.go | 79 +- cmd/account/iam-v2/iam-v2.go | 528 +- cmd/account/settings-v2/settings-v2.go | 42 +- cmd/workspace/alerts-v2/alerts-v2.go | 2 +- cmd/workspace/apps/apps.go | 2 + .../bundle-deployments/bundle-deployments.go | 82 + .../feature-engineering.go | 8 - cmd/workspace/genie/genie.go | 77 +- cmd/workspace/groups.go | 2 +- .../lakeview-embedded/lakeview-embedded.go | 3 + cmd/workspace/lakeview/lakeview.go | 25 +- cmd/workspace/policies/policies.go | 16 + cmd/workspace/postgres/postgres.go | 573 ++ .../workspace-iam-v2/workspace-iam-v2.go | 555 +- .../workspace-settings-v2.go | 42 +- go.mod | 2 +- go.sum | 4 +- .../bundles/alerts/_models/alert.py | 26 +- .../_models/alert_statement_parameter.py | 27 +- python/databricks/bundles/jobs/__init__.py | 11 + .../bundles/jobs/_models/alert_task.py | 30 +- .../bundles/jobs/_models/cluster_spec.py | 4 +- .../bundles/jobs/_models/continuous.py | 18 + .../continuous_trigger_configuration.py | 20 + .../bundles/jobs/_models/dashboard_task.py | 5 +- .../bundles/jobs/_models/day_of_week.py | 28 + .../jobs/_models/hardware_accelerator_type.py | 3 +- python/databricks/bundles/jobs/_models/job.py | 4 + .../jobs/_models/maintenance_window.py | 82 + .../jobs/_models/node_type_flexibility.py | 14 +- .../jobs/_models/trigger_configuration.py | 6 +- .../databricks/bundles/pipelines/__init__.py | 8 + .../pipelines/_models/connector_options.py | 20 + .../pipelines/_models/ingestion_config.py | 5 +- .../bundles/pipelines/_models/pipeline.py | 12 +- .../pipelines/_models/pipeline_cluster.py | 4 +- .../_models/pipelines_environment.py | 4 +- .../pipelines/_models/rabbitmq_options.py | 45 + .../bundles/pipelines/_models/schema_spec.py | 32 +- .../bundles/pipelines/_models/table_spec.py | 32 +- 53 files changed, 5904 insertions(+), 1802 deletions(-) create mode 100644 .nextchanges/dependency-updates/bump-sdk-0.177.0.md create mode 100644 python/databricks/bundles/jobs/_models/day_of_week.py create mode 100644 python/databricks/bundles/jobs/_models/maintenance_window.py create mode 100644 python/databricks/bundles/pipelines/_models/rabbitmq_options.py diff --git a/.codegen/_openapi_sha b/.codegen/_openapi_sha index e1ef04f4fce..a2586cb81f6 100644 --- a/.codegen/_openapi_sha +++ b/.codegen/_openapi_sha @@ -1 +1 @@ -b73946692eb938a39aa3c6a863873f99eadde611 \ No newline at end of file +0f2c9a3d507d46e8726ac09e0348d52d3f9c9bc8 \ No newline at end of file diff --git a/.codegen/cli.json b/.codegen/cli.json index b17b9a95064..b659b2606d2 100644 --- a/.codegen/cli.json +++ b/.codegen/cli.json @@ -2885,6 +2885,13 @@ }, "apps.Space": { "fields": { + "assume_group_id": { + "description": "The group whose permissions users assume via Role Authorization for apps in this space. When\nset, user tokens assume the role of this group instead of doing regular obo token downscoping.\nSet only at space creation.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OPTIONAL" + ] + }, "create_time": { "description": "The creation time of the app space. Formatted timestamp in ISO 6801.", "launch_stage": "PRIVATE_PREVIEW", @@ -4092,7 +4099,7 @@ "bundledeployments.CreateDeploymentRequest": { "fields": { "deployment": { - "description": "The deployment to create. The caller must set `initial_parent_path`. Other fields are ignored\non input and populated by the service.", + "description": "The deployment to create. `initial_parent_path` is required. `display_name`, `target_name`,\n`deployment_mode`, and `workspace_info` may be set; every other field is assigned by the\nservice and ignored on input.", "ref": "bundledeployments.Deployment", "launch_stage": "PRIVATE_PREVIEW" } @@ -4115,7 +4122,7 @@ "description": "Dashboard-specific per-resource metadata. Set only for dashboard resources.", "fields": { "definition_path": { - "description": "Path of the file that declares this dashboard, relative to the bundle's\nworkspace.file_path (Version.workspace_info.file_path) — join the two to\nget the file's absolute workspace path.\n\nFor now this lives only on the dashboard metadata, and is a single string\nbecause it was a single string (`relative_path`) in the legacy bundle\nmetadata.json. We may generalize it in the future: lifting it to a\ntop-level field on Resource/Operation (every resource type has a definition\nlocation) and converting it to a repeated field, since a resource can be\ndeclared across multiple files/locations.", + "description": "Path of the file that declares this dashboard, relative to the bundle's\nworkspace.file_path (Deployment.workspace_info.file_path) — join the two to\nget the file's absolute workspace path.\n\nFor now this lives only on the dashboard metadata, and is a single string\nbecause it was a single string (`relative_path`) in the legacy bundle\nmetadata.json. We may generalize it in the future: lifting it to a\ntop-level field on Resource/Operation (every resource type has a definition\nlocation) and converting it to a repeated field, since a resource can be\ndeclared across multiple files/locations.", "launch_stage": "PRIVATE_PREVIEW" }, "source_path": { @@ -4143,12 +4150,9 @@ ] }, "deployment_mode": { - "description": "Bundle target deployment mode (development or production), derived from the\nmost recent version's mode.", + "description": "Bundle target deployment mode (development or production).", "ref": "bundledeployments.DeploymentMode", - "launch_stage": "PRIVATE_PREVIEW", - "behaviors": [ - "OUTPUT_ONLY" - ] + "launch_stage": "PRIVATE_PREVIEW" }, "destroy_time": { "description": "When deletion was recorded. Unset if deletion has not been recorded.\nThis response metadata does not determine the deployment's lifecycle status.", @@ -4165,11 +4169,8 @@ ] }, "display_name": { - "description": "Human-readable name for the deployment, up to 256 characters. Output only: clients update it\nby setting `display_name` when creating a version.", - "launch_stage": "PRIVATE_PREVIEW", - "behaviors": [ - "OUTPUT_ONLY" - ] + "description": "Human-readable name for the deployment, up to 256 characters.", + "launch_stage": "PRIVATE_PREVIEW" }, "git_info": { "description": "Git provenance of the deployment's source, derived from the latest version.", @@ -4216,11 +4217,8 @@ ] }, "target_name": { - "description": "The bundle target name associated with this deployment. Output only: it is\ndenormalized from the latest version, not set directly on the deployment.", - "launch_stage": "PRIVATE_PREVIEW", - "behaviors": [ - "OUTPUT_ONLY" - ] + "description": "The bundle target name associated with this deployment.", + "launch_stage": "PRIVATE_PREVIEW" }, "update_time": { "description": "When the deployment was last updated.", @@ -4237,12 +4235,9 @@ ] }, "workspace_info": { - "description": "Workspace location of the deployment, derived from the latest version.", + "description": "Workspace location of the deployment.", "ref": "bundledeployments.WorkspaceInfo", - "launch_stage": "PRIVATE_PREVIEW", - "behaviors": [ - "OUTPUT_ONLY" - ] + "launch_stage": "PRIVATE_PREVIEW" } } }, @@ -4282,7 +4277,16 @@ "DEPLOYMENT_RESOURCE_TYPE_SYNCED_DATABASE_TABLE", "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_PROJECT", "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_BRANCH", - "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_ENDPOINT" + "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_ENDPOINT", + "DEPLOYMENT_RESOURCE_TYPE_VECTOR_SEARCH_ENDPOINT", + "DEPLOYMENT_RESOURCE_TYPE_VECTOR_SEARCH_INDEX", + "DEPLOYMENT_RESOURCE_TYPE_JOB_RUN", + "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_CATALOG", + "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_SYNCED_TABLE", + "DEPLOYMENT_RESOURCE_TYPE_GENIE_SPACE", + "DEPLOYMENT_RESOURCE_TYPE_INSTANCE_POOL", + "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_DATABASE", + "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_ROLE" ], "enum_launch_stages": { "DEPLOYMENT_RESOURCE_TYPE_ALERT": "PRIVATE_PREVIEW", @@ -4294,19 +4298,28 @@ "DEPLOYMENT_RESOURCE_TYPE_DATABASE_INSTANCE": "PRIVATE_PREVIEW", "DEPLOYMENT_RESOURCE_TYPE_EXPERIMENT": "PRIVATE_PREVIEW", "DEPLOYMENT_RESOURCE_TYPE_EXTERNAL_LOCATION": "PRIVATE_PREVIEW", + "DEPLOYMENT_RESOURCE_TYPE_GENIE_SPACE": "PRIVATE_PREVIEW", + "DEPLOYMENT_RESOURCE_TYPE_INSTANCE_POOL": "PRIVATE_PREVIEW", "DEPLOYMENT_RESOURCE_TYPE_JOB": "PRIVATE_PREVIEW", + "DEPLOYMENT_RESOURCE_TYPE_JOB_RUN": "PRIVATE_PREVIEW", "DEPLOYMENT_RESOURCE_TYPE_MODEL": "PRIVATE_PREVIEW", "DEPLOYMENT_RESOURCE_TYPE_MODEL_SERVING_ENDPOINT": "PRIVATE_PREVIEW", "DEPLOYMENT_RESOURCE_TYPE_PIPELINE": "PRIVATE_PREVIEW", "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_BRANCH": "PRIVATE_PREVIEW", + "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_CATALOG": "PRIVATE_PREVIEW", + "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_DATABASE": "PRIVATE_PREVIEW", "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_ENDPOINT": "PRIVATE_PREVIEW", "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_PROJECT": "PRIVATE_PREVIEW", + "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_ROLE": "PRIVATE_PREVIEW", + "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_SYNCED_TABLE": "PRIVATE_PREVIEW", "DEPLOYMENT_RESOURCE_TYPE_QUALITY_MONITOR": "PRIVATE_PREVIEW", "DEPLOYMENT_RESOURCE_TYPE_REGISTERED_MODEL": "PRIVATE_PREVIEW", "DEPLOYMENT_RESOURCE_TYPE_SCHEMA": "PRIVATE_PREVIEW", "DEPLOYMENT_RESOURCE_TYPE_SECRET_SCOPE": "PRIVATE_PREVIEW", "DEPLOYMENT_RESOURCE_TYPE_SQL_WAREHOUSE": "PRIVATE_PREVIEW", "DEPLOYMENT_RESOURCE_TYPE_SYNCED_DATABASE_TABLE": "PRIVATE_PREVIEW", + "DEPLOYMENT_RESOURCE_TYPE_VECTOR_SEARCH_ENDPOINT": "PRIVATE_PREVIEW", + "DEPLOYMENT_RESOURCE_TYPE_VECTOR_SEARCH_INDEX": "PRIVATE_PREVIEW", "DEPLOYMENT_RESOURCE_TYPE_VOLUME": "PRIVATE_PREVIEW" } }, @@ -4619,10 +4632,12 @@ "description": "Status of a resource operation.", "enum": [ "OPERATION_STATUS_SUCCEEDED", - "OPERATION_STATUS_FAILED" + "OPERATION_STATUS_FAILED", + "OPERATION_STATUS_PENDING" ], "enum_launch_stages": { "OPERATION_STATUS_FAILED": "PRIVATE_PREVIEW", + "OPERATION_STATUS_PENDING": "PRIVATE_PREVIEW", "OPERATION_STATUS_SUCCEEDED": "PRIVATE_PREVIEW" } }, @@ -4697,6 +4712,33 @@ } } }, + "bundledeployments.StagedOperation": { + "description": "A resource operation to record when a version is created. Each staged\noperation identifies the resource it applies to and the action planned for\nit; the server records the operation in `OPERATION_STATUS_PENDING`, and its\noutcome is filled in later via UpdateOperation.", + "fields": { + "action_type": { + "description": "The type of operation planned for this resource.", + "ref": "bundledeployments.OperationActionType", + "launch_stage": "PRIVATE_PREVIEW" + }, + "resource_key": { + "description": "The key identifying the resource this operation applies to (e.g.\n\"jobs.foo\", \"pipelines.bar\"). Becomes the final component of the\noperation's name and must be unique among the operations in the version.", + "launch_stage": "PRIVATE_PREVIEW" + } + } + }, + "bundledeployments.UpdateDeploymentRequest": { + "fields": { + "deployment": { + "description": "The deployment to update. Its `name` selects the deployment; the fields\nnamed in `update_mask` carry the new values. All other fields are ignored.", + "ref": "bundledeployments.Deployment", + "launch_stage": "PRIVATE_PREVIEW" + }, + "update_mask": { + "description": "The fields to update; supported paths are `display_name`, `deployment_mode`, `target_name`,\nand `workspace_info`. An empty mask or any other path returns INVALID_PARAMETER_VALUE.", + "launch_stage": "PRIVATE_PREVIEW" + } + } + }, "bundledeployments.UpdateOperationRequest": { "fields": { "operation": { @@ -4786,6 +4828,14 @@ "OUTPUT_ONLY" ] }, + "operations": { + "description": "The full operation plan for this version: one PENDING operation per entry,\nrecorded in the same transaction. Input only -- supplied on create and never\nreturned by create/get/list; read the recorded operations via ListOperations.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "INPUT_ONLY", + "OPTIONAL" + ] + }, "previous_version_id": { "description": "The version_id this version was created on top of — the deployment's\nmost recent version at creation time. Leave unset when creating the\nfirst version (the deployment has no prior versions). Set by the\nclient on creation and immutable thereafter.\n\nActs as an optimistic-concurrency precondition: the server requires\nit to equal the deployment's current most-recent version (and to be\nunset when the deployment has no versions) and returns\n`INVALID_PARAMETER_VALUE` on mismatch, so a deploy racing against a\nconcurrent deploy is rejected rather than silently overwriting it.", "launch_stage": "PRIVATE_PREVIEW", @@ -5593,12 +5643,12 @@ "launch_stage": "GA" }, "using_arguments": { - "description": "The list of additional table columns or literals to be passed as additional arguments to\na column mask function. This is the replacement of the deprecated using_column_names field and\ncarries information about the types (alias or constant) of the arguments to the mask function.", + "description": "The list of table columns or literals to be passed as additional arguments to a column mask\nfunction, carrying the type (column reference vs constant literal) of each argument.\nDeprecated: use using_column_names instead.", + "deprecated": true, "launch_stage": "GA" }, "using_column_names": { "description": "The list of additional table columns to be passed as input to the column mask function. The\nfirst arg of the mask function should be of the type of the column being masked and the\ntypes of the rest of the args should match the types of columns in 'using_column_names'.", - "deprecated": true, "launch_stage": "GA" } } @@ -5632,6 +5682,19 @@ } } }, + "catalog.ColumnTagValueExtraction": { + "description": "Extracts the value of a column-level tag: get_column_tag_value(col, \"tagKey\").", + "fields": { + "column_alias": { + "description": "The alias from MATCH COLUMNS that identifies the column.", + "launch_stage": "GA" + }, + "tag_key": { + "description": "1024 matches the max_length on FunctionArgument.constant above.", + "launch_stage": "GA" + } + } + }, "catalog.ColumnTypeName": { "enum": [ "BOOLEAN", @@ -7918,6 +7981,19 @@ } } }, + "catalog.FunctionArgExpression": { + "description": "An expression that is evaluated at query time against per-request context.\nNew variants (e.g., identity attributes) are added as additional oneof cases.", + "fields": { + "tag_introspection": { + "description": "An expression that introspects tags at query time.", + "ref": "catalog.TagIntrospectionExpression", + "launch_stage": "GA", + "behaviors": [ + "OPTIONAL" + ] + } + } + }, "catalog.FunctionArgument": { "fields": { "alias": { @@ -7927,6 +8003,14 @@ "constant": { "description": "A constant literal.", "launch_stage": "GA" + }, + "function_arg_expression": { + "description": "An expression evaluated at query time. Wraps per-request expression variants\n(e.g., tag introspection) so new variants can be added without extending the\nFunctionArgument oneof.", + "ref": "catalog.FunctionArgExpression", + "launch_stage": "GA", + "behaviors": [ + "OPTIONAL" + ] } } }, @@ -12539,7 +12623,11 @@ "CONNECTION", "CREDENTIAL", "EXTERNAL_METADATA", - "STAGING_TABLE" + "STAGING_TABLE", + "MODEL", + "MODEL_SERVICE", + "MCP_SERVICE", + "MODEL_PROVIDER_SERVICE" ], "enum_launch_stages": { "CATALOG": "GA", @@ -12549,7 +12637,11 @@ "EXTERNAL_LOCATION": "GA", "EXTERNAL_METADATA": "GA", "FUNCTION": "GA", + "MCP_SERVICE": "PUBLIC_BETA", "METASTORE": "GA", + "MODEL": "PUBLIC_BETA", + "MODEL_PROVIDER_SERVICE": "PUBLIC_BETA", + "MODEL_SERVICE": "PUBLIC_BETA", "PIPELINE": "GA", "PROVIDER": "GA", "RECIPIENT": "GA", @@ -12986,12 +13078,12 @@ "launch_stage": "GA" }, "input_arguments": { - "description": "The list of additional table columns or literals to be passed as additional arguments to\na row filter function. This is the replacement of the deprecated input_column_names field and\ncarries information about the types (alias or constant) of the arguments to the filter function.", + "description": "The list of table columns or literals to be passed as additional arguments to a row filter\nfunction, carrying the type (column reference vs constant literal) of each argument.\nDeprecated: use input_column_names instead.", + "deprecated": true, "launch_stage": "GA" }, "input_column_names": { "description": "The list of table columns to be passed as input to the row filter function. The column types\nshould match the types of the filter function arguments.", - "deprecated": true, "launch_stage": "GA" } } @@ -13046,6 +13138,27 @@ "TAG_ASSIGNMENT_SOURCE_TYPE_SYSTEM_DATA_CLASSIFICATION": "GA" } }, + "catalog.TagIntrospectionExpression": { + "description": "An expression that introspects tags at query time.", + "fields": { + "column_tag_value": { + "description": "Extracts the value of a column-level tag.", + "ref": "catalog.ColumnTagValueExtraction", + "launch_stage": "GA", + "behaviors": [ + "OPTIONAL" + ] + }, + "tag_value": { + "description": "Extracts the value of a securable-level tag.", + "ref": "catalog.TagValueExtraction", + "launch_stage": "GA", + "behaviors": [ + "OPTIONAL" + ] + } + } + }, "catalog.TagKeyValue": { "fields": { "key": { @@ -13058,6 +13171,15 @@ } } }, + "catalog.TagValueExtraction": { + "description": "Extracts the value of a securable-level tag: get_tag_value(\"tagKey\").", + "fields": { + "tag_key": { + "description": "1024 matches the max_length on FunctionArgument.constant above.", + "launch_stage": "GA" + } + } + }, "catalog.TemporaryCredentials": { "fields": { "aws_temp_credentials": { @@ -15883,7 +16005,7 @@ "launch_stage": "GA" }, "total_initial_remote_disk_size": { - "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Currently only supported for GCP HYPERDISK_BALANCED disks.", + "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Supported for GCP.", "launch_stage": "GA" }, "use_ml_runtime": { @@ -16137,7 +16259,7 @@ "launch_stage": "GA" }, "total_initial_remote_disk_size": { - "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Currently only supported for GCP HYPERDISK_BALANCED disks.", + "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Supported for GCP.", "launch_stage": "GA" }, "use_ml_runtime": { @@ -16546,7 +16668,7 @@ "launch_stage": "GA" }, "total_initial_remote_disk_size": { - "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Currently only supported for GCP HYPERDISK_BALANCED disks.", + "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Supported for GCP.", "launch_stage": "GA" }, "use_ml_runtime": { @@ -16823,7 +16945,7 @@ "launch_stage": "GA" }, "total_initial_remote_disk_size": { - "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Currently only supported for GCP HYPERDISK_BALANCED disks.", + "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Supported for GCP.", "launch_stage": "GA" }, "use_ml_runtime": { @@ -17375,7 +17497,7 @@ "launch_stage": "GA" }, "total_initial_remote_disk_size": { - "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Currently only supported for GCP HYPERDISK_BALANCED disks.", + "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Supported for GCP.", "launch_stage": "GA" }, "use_ml_runtime": { @@ -17649,7 +17771,7 @@ "launch_stage": "GA" }, "total_initial_remote_disk_size": { - "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Currently only supported for GCP HYPERDISK_BALANCED disks.", + "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Supported for GCP.", "launch_stage": "GA" }, "use_ml_runtime": { @@ -18354,10 +18476,12 @@ "description": "HardwareAcceleratorType: The type of hardware accelerator to use for compute workloads.\nNOTE: This enum is referenced and is intended to be used by other Databricks services\nthat need to specify hardware accelerator requirements for AI compute workloads.", "enum": [ "GPU_1xA10", - "GPU_8xH100" + "GPU_8xH100", + "GPU_1xH100" ], "enum_launch_stages": { "GPU_1xA10": "PUBLIC_BETA", + "GPU_1xH100": "PUBLIC_BETA", "GPU_8xH100": "PUBLIC_BETA" } }, @@ -19351,6 +19475,10 @@ "alternate_node_type_ids": { "description": "A list of node type IDs to use as fallbacks when the primary node type is unavailable.", "launch_stage": "GA" + }, + "aws_context_id": { + "description": "The AWS Context ID for EC2 Fleet.\nWhen set (non-empty), the value is passed to AWS CreateFleet API to create the EC2 Fleet.", + "launch_stage": "GA" } } }, @@ -20327,7 +20455,7 @@ "launch_stage": "GA" }, "total_initial_remote_disk_size": { - "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Currently only supported for GCP HYPERDISK_BALANCED disks.", + "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Supported for GCP.", "launch_stage": "GA" }, "use_ml_runtime": { @@ -20540,7 +20668,7 @@ "dashboards.DownloadMessageAttachmentVisualizationResponse": { "fields": { "contents": { - "launch_stage": "PUBLIC_BETA" + "launch_stage": "GA" } } }, @@ -20599,13 +20727,16 @@ "viz": { "description": "Visualization generated by Genie, if requested via `enable_visualization`", "ref": "dashboards.GenieVizAttachment", - "launch_stage": "PUBLIC_BETA", + "launch_stage": "GA", "behaviors": [ "OUTPUT_ONLY" ] } } }, + "dashboards.GenieCancelResponseRequest": { + "description": "Request to cancel an in-flight agent-mode response." + }, "dashboards.GenieConversation": { "fields": { "conversation_id": { @@ -20656,7 +20787,7 @@ "agent_type": { "description": "Whether this is a classic chat or an agent-mode conversation. Allows callers to\nroute message retrieval (chat vs. agent endpoint) without an extra lookup.", "ref": "dashboards.GenieConversationType", - "launch_stage": "PUBLIC_BETA", + "launch_stage": "GA", "behaviors": [ "OUTPUT_ONLY" ] @@ -20685,8 +20816,8 @@ "GENIE_CONVERSATION_TYPE_AGENT" ], "enum_launch_stages": { - "GENIE_CONVERSATION_TYPE_AGENT": "PUBLIC_BETA", - "GENIE_CONVERSATION_TYPE_CHAT": "PUBLIC_BETA" + "GENIE_CONVERSATION_TYPE_AGENT": "GA", + "GENIE_CONVERSATION_TYPE_CHAT": "GA" } }, "dashboards.GenieCreateConversationMessageRequest": { @@ -20697,7 +20828,7 @@ }, "enable_visualization": { "description": "Enable visualization generation.", - "launch_stage": "PUBLIC_BETA", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -21560,7 +21691,7 @@ }, "enable_visualization": { "description": "Enable visualization generation.", - "launch_stage": "PUBLIC_BETA", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -21651,14 +21782,14 @@ "fields": { "query_attachment_id": { "description": "The ID of the query attachment the visualization was generated from", - "launch_stage": "PUBLIC_BETA", + "launch_stage": "GA", "behaviors": [ "OUTPUT_ONLY" ] }, "title": { "description": "Name of the visualization", - "launch_stage": "PUBLIC_BETA", + "launch_stage": "GA", "behaviors": [ "OUTPUT_ONLY" ] @@ -22307,7 +22438,7 @@ ], "enum_launch_stages": { "FOLLOW_UP_QUESTION": "GA", - "TEXT_ATTACHMENT_PURPOSE_ANSWER": "PUBLIC_BETA" + "TEXT_ATTACHMENT_PURPOSE_ANSWER": "GA" } }, "dashboards.Thought": { @@ -27242,7 +27373,7 @@ "direct_group_member": { "description": "Required. The group membership to create.", "ref": "iamv2.DirectGroupMember", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -27251,7 +27382,7 @@ "direct_group_member": { "description": "Required. The direct group member to be added to the group.", "ref": "iamv2.DirectGroupMember", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -27260,7 +27391,7 @@ "group": { "description": "Required. Group to be created in \u003cDatabricks\u003e", "ref": "iamv2.Group", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -27269,7 +27400,7 @@ "group": { "description": "Required. Group to be created in \u003cDatabricks\u003e", "ref": "iamv2.Group", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -27278,7 +27409,7 @@ "service_principal": { "description": "Required. Service principal to be created in \u003cDatabricks\u003e", "ref": "iamv2.ServicePrincipal", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -27287,7 +27418,7 @@ "service_principal": { "description": "Required. Service principal to be created in \u003cDatabricks\u003e", "ref": "iamv2.ServicePrincipal", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -27296,7 +27427,7 @@ "user": { "description": "Required. User to be created in \u003cDatabricks\u003e", "ref": "iamv2.User", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -27305,7 +27436,7 @@ "user": { "description": "Required. User to be created in \u003cDatabricks\u003e", "ref": "iamv2.User", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -27332,7 +27463,7 @@ "workspace_assignment": { "description": "Required. Workspace assignment to be created in \u003cDatabricks\u003e.", "ref": "iamv2.WorkspaceAssignment", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -27341,7 +27472,7 @@ "workspace_assignment": { "description": "Required. Workspace assignment to be created in \u003cDatabricks\u003e.", "ref": "iamv2.WorkspaceAssignment", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -27362,21 +27493,21 @@ "fields": { "display_name": { "description": "Display name of the principal.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OUTPUT_ONLY" ] }, "external_id": { "description": "The external ID of the principal in Databricks.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OUTPUT_ONLY" ] }, "group_id": { "description": "The internal ID of the group this member belongs to.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL", "OUTPUT_ONLY" @@ -27385,14 +27516,14 @@ "membership_source": { "description": "The source of group membership (internal or from identity provider).", "ref": "iamv2.GroupMembershipSource", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OUTPUT_ONLY" ] }, "principal_id": { "description": "Internal ID of the principal in Databricks.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "IMMUTABLE" ] @@ -27400,7 +27531,7 @@ "principal_type": { "description": "The type of the principal (user/service principal/group).", "ref": "iamv2.PrincipalType", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OUTPUT_ONLY" ] @@ -27417,16 +27548,199 @@ "ALLOW_INSTANCE_POOL_CREATE" ], "enum_launch_stages": { - "ALLOW_CLUSTER_CREATE": "PRIVATE_PREVIEW", - "ALLOW_INSTANCE_POOL_CREATE": "PRIVATE_PREVIEW", - "DATABRICKS_SQL_ACCESS": "PRIVATE_PREVIEW", - "WORKSPACE_ACCESS": "PRIVATE_PREVIEW", - "WORKSPACE_ADMIN": "PRIVATE_PREVIEW", - "WORKSPACE_CONSUME": "PRIVATE_PREVIEW" + "ALLOW_CLUSTER_CREATE": "PUBLIC_BETA", + "ALLOW_INSTANCE_POOL_CREATE": "PUBLIC_BETA", + "DATABRICKS_SQL_ACCESS": "PUBLIC_BETA", + "WORKSPACE_ACCESS": "PUBLIC_BETA", + "WORKSPACE_ADMIN": "PUBLIC_BETA", + "WORKSPACE_CONSUME": "PUBLIC_BETA" + } + }, + "iamv2.ExternalGroup": { + "description": "An external group from the customer's Identity Provider, resolved into\nDatabricks. This is a read-only resource keyed by the IdP external ID.\nThe Get method may trigger an idempotent sync from the customer's IdP to\nprovision or refresh the group's data in Databricks.", + "fields": { + "account_id": { + "description": "The parent account ID, from Databricks.", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "display_name": { + "description": "Display name of the group from the customer's IdP.", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "external_group_id": { + "description": "The external ID of the group in the customer's IdP.", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "internal_id": { + "description": "Internal groupId of the group in Databricks.", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "name": { + "description": "The resource name of the external group. The format depends on the API that\nreturned it:\n- Account-scoped: accounts/{account_id}/external-groups/{external_group_id}\n- Workspace-scoped: external-groups/{external_group_id}", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + } + } + }, + "iamv2.ExternalServicePrincipal": { + "description": "An external service principal from the customer's Identity Provider, resolved\ninto Databricks. This is a read-only resource keyed by the IdP external ID.\nThe Get method may trigger an idempotent sync from the customer's IdP to\nprovision or refresh the service principal's data in Databricks.", + "fields": { + "account_id": { + "description": "The parent account ID, from Databricks.", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "account_sp_status": { + "description": "The activity status of the service principal in the Databricks account.", + "ref": "iamv2.State", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "application_id": { + "description": "Application ID of the service principal, from the customer's IdP.", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "display_name": { + "description": "Display name of the service principal, from the customer's IdP.", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "external_service_principal_id": { + "description": "The external ID of the service principal in the customer's IdP.", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "internal_id": { + "description": "Internal servicePrincipalId of the service principal in Databricks.", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "name": { + "description": "The resource name of the external service principal. The format depends on\nthe API that returned it:\n- Account-scoped: accounts/{account_id}/external-service-principals/{external_service_principal_id}\n- Workspace-scoped: external-service-principals/{external_service_principal_id}", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + } + } + }, + "iamv2.ExternalUser": { + "description": "An external user from the customer's Identity Provider, resolved into\nDatabricks. This is a read-only resource that allows customers to look up\nexternal user identities by their IdP external ID and retrieve the\ncorresponding Databricks internal ID and metadata. The Get method may\ntrigger an idempotent sync from the customer's IdP to provision or refresh\nthe user's data in Databricks.", + "fields": { + "account_id": { + "description": "The parent account ID, from Databricks.", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "account_user_status": { + "description": "The activity status of the user in the Databricks account.", + "ref": "iamv2.State", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "display_name": { + "description": "Display name of the user from the customer's IdP.", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "external_user_id": { + "description": "The external ID of the user in the customer's IdP.", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "full_name": { + "description": "The full name of the user, from the customer's IdP.", + "ref": "iamv2.FullName", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "internal_id": { + "description": "Internal userId of the user in Databricks.", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "name": { + "description": "The resource name of the external user. The format depends on the API that\nreturned it:\n- Account-scoped: accounts/{account_id}/external-users/{external_user_id}\n- Workspace-scoped: external-users/{external_user_id}", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "username": { + "description": "Username/email of the user, from Databricks.", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + } + } + }, + "iamv2.FullName": { + "description": "The full name of a user.", + "fields": { + "family_name": { + "description": "The family (last) name of the user, from the customer's IdP.", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "given_name": { + "description": "The given (first) name of the user, from the customer's IdP.", + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OUTPUT_ONLY" + ] + } } }, "iamv2.GetDirectGroupMemberProxyRequest": {}, "iamv2.GetDirectGroupMemberRequest": {}, + "iamv2.GetExternalGroupProxyRequest": {}, + "iamv2.GetExternalGroupRequest": {}, + "iamv2.GetExternalServicePrincipalProxyRequest": {}, + "iamv2.GetExternalServicePrincipalRequest": {}, + "iamv2.GetExternalUserProxyRequest": {}, + "iamv2.GetExternalUserRequest": {}, "iamv2.GetGroupProxyRequest": {}, "iamv2.GetGroupRequest": {}, "iamv2.GetServicePrincipalProxyRequest": {}, @@ -27502,22 +27816,22 @@ "IDENTITY_PROVIDER" ], "enum_launch_stages": { - "IDENTITY_PROVIDER": "PRIVATE_PREVIEW", - "INTERNAL": "PRIVATE_PREVIEW" + "IDENTITY_PROVIDER": "PUBLIC_BETA", + "INTERNAL": "PUBLIC_BETA" } }, "iamv2.ListDirectGroupMembersProxyRequest": { "fields": { "page_size": { - "description": "The maximum number of members to return. The service may return fewer than this value.\nIf not provided, defaults to 1000 (also the maximum allowed).", - "launch_stage": "PRIVATE_PREVIEW", + "description": "The maximum number of members to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_token": { "description": "A page token from a previous list call. Provide this to retrieve the subsequent page.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] @@ -27527,15 +27841,15 @@ "iamv2.ListDirectGroupMembersRequest": { "fields": { "page_size": { - "description": "The maximum number of members to return. The service may return fewer than this value.\nIf not provided, defaults to 1000 (also the maximum allowed).", - "launch_stage": "PRIVATE_PREVIEW", + "description": "The maximum number of members to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_token": { "description": "A page token, received from a previous ListDirectGroupMembers call. Provide this to retrieve the subsequent page.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] @@ -27547,11 +27861,11 @@ "fields": { "direct_group_members": { "description": "The list of direct group members with their membership source type.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" }, "next_page_token": { "description": "A token, which can be sent as page_token to retrieve the next page. If this field is omitted, there are no subsequent pages.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -27559,21 +27873,21 @@ "fields": { "filter": { "description": "Optional. Allows filtering groups by group name or external id.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_size": { - "description": "The maximum number of groups to return. The service may return fewer than this value.", - "launch_stage": "PRIVATE_PREVIEW", + "description": "The maximum number of groups to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_token": { "description": "A page token, received from a previous ListGroups call. Provide this to retrieve the subsequent page.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] @@ -27584,21 +27898,21 @@ "fields": { "filter": { "description": "Optional. Allows filtering groups by group name or external id.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_size": { - "description": "The maximum number of groups to return. The service may return fewer than this value.", - "launch_stage": "PRIVATE_PREVIEW", + "description": "The maximum number of groups to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_token": { "description": "A page token, received from a previous ListGroups call. Provide this to retrieve the subsequent page.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] @@ -27609,11 +27923,11 @@ "description": "Response message containing a page of groups in the account.", "fields": { "groups": { - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" }, "next_page_token": { "description": "A token, which can be sent as page_token to retrieve the next page. If this field is omitted, there are no subsequent pages.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -27621,21 +27935,21 @@ "fields": { "filter": { "description": "Optional. Allows filtering service principals by application id or external id.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_size": { - "description": "The maximum number of SPs to return. The service may return fewer than this value.", - "launch_stage": "PRIVATE_PREVIEW", + "description": "The maximum number of SPs to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_token": { "description": "A page token, received from a previous ListServicePrincipals call. Provide this to retrieve the subsequent page.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] @@ -27646,21 +27960,21 @@ "fields": { "filter": { "description": "Optional. Allows filtering service principals by application id or external id.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_size": { - "description": "The maximum number of service principals to return. The service may return fewer than this value.", - "launch_stage": "PRIVATE_PREVIEW", + "description": "The maximum number of service principals to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_token": { "description": "A page token, received from a previous ListServicePrincipals call. Provide this to retrieve the subsequent page.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] @@ -27672,25 +27986,25 @@ "fields": { "next_page_token": { "description": "A token, which can be sent as page_token to retrieve the next page. If this field is omitted, there are no subsequent pages.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" }, "service_principals": { - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, "iamv2.ListTransitiveParentGroupsProxyRequest": { "fields": { "page_size": { - "description": "The maximum number of parent groups to return. The service may return fewer than this value.\nIf not provided, defaults to 1000 (also the maximum allowed).", - "launch_stage": "PRIVATE_PREVIEW", + "description": "The maximum number of parent groups to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_token": { "description": "A page token, received from a previous ListTransitiveParentGroups call. Provide this to retrieve the subsequent page.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] @@ -27700,15 +28014,15 @@ "iamv2.ListTransitiveParentGroupsRequest": { "fields": { "page_size": { - "description": "The maximum number of parent groups to return. The service may return fewer than this value.\nIf not provided, defaults to 1000 (also the maximum allowed).", - "launch_stage": "PRIVATE_PREVIEW", + "description": "The maximum number of parent groups to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_token": { "description": "A page token, received from a previous ListTransitiveParentGroups call. Provide this to retrieve the subsequent page.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] @@ -27720,11 +28034,11 @@ "fields": { "next_page_token": { "description": "A token, which can be sent as page_token to retrieve the next page. If this field is omitted, there are no subsequent pages.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" }, "transitive_parent_groups": { "description": "The list of transitive parent groups.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -27732,21 +28046,21 @@ "fields": { "filter": { "description": "Optional. Allows filtering users by username or external id.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_size": { - "description": "The maximum number of users to return. The service may return fewer than this value.", - "launch_stage": "PRIVATE_PREVIEW", + "description": "The maximum number of users to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_token": { "description": "A page token, received from a previous ListUsers call. Provide this to retrieve the subsequent page.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] @@ -27757,21 +28071,21 @@ "fields": { "filter": { "description": "Optional. Allows filtering users by username or external id.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_size": { - "description": "The maximum number of users to return. The service may return fewer than this value.", - "launch_stage": "PRIVATE_PREVIEW", + "description": "The maximum number of users to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_token": { "description": "A page token, received from a previous ListUsers call. Provide this to retrieve the subsequent page.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] @@ -27782,17 +28096,17 @@ "fields": { "next_page_token": { "description": "A token, which can be sent as page_token to retrieve the next page. If this field is omitted, there are no subsequent pages.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" }, "users": { - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, "iamv2.ListWorkspaceAssignmentDetailsProxyRequest": { "fields": { "page_size": { - "description": "The maximum number of workspace assignment details to return. The service may return fewer than this value.", + "description": "The maximum number of workspace assignment details to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", "launch_stage": "PRIVATE_PREVIEW", "behaviors": [ "OPTIONAL" @@ -27810,7 +28124,7 @@ "iamv2.ListWorkspaceAssignmentDetailsRequest": { "fields": { "page_size": { - "description": "The maximum number of workspace assignment details to return. The service may return fewer than this value.", + "description": "The maximum number of workspace assignment details to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", "launch_stage": "PRIVATE_PREVIEW", "behaviors": [ "OPTIONAL" @@ -27840,15 +28154,15 @@ "iamv2.ListWorkspaceAssignmentsProxyRequest": { "fields": { "page_size": { - "description": "The maximum number of workspace assignments to return. The service may return fewer than this value.", - "launch_stage": "PRIVATE_PREVIEW", + "description": "The maximum number of workspace assignments to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_token": { "description": "A page token from a previous list call. Provide this to retrieve the subsequent page.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] @@ -27858,15 +28172,15 @@ "iamv2.ListWorkspaceAssignmentsRequest": { "fields": { "page_size": { - "description": "The maximum number of workspace assignments to return. The service may return fewer than this value.", - "launch_stage": "PRIVATE_PREVIEW", + "description": "The maximum number of workspace assignments to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] }, "page_token": { "description": "A page token, received from a previous ListWorkspaceAssignments call. Provide this to retrieve the subsequent page.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] @@ -27878,10 +28192,10 @@ "fields": { "next_page_token": { "description": "A token, which can be sent as page_token to retrieve the next page. If this field is omitted, there are no subsequent pages.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" }, "workspace_assignments": { - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -28038,21 +28352,21 @@ "fields": { "account_id": { "description": "The parent account ID for group in Databricks.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OUTPUT_ONLY" ] }, "external_id": { "description": "ExternalId of the group in the customer's IdP.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OUTPUT_ONLY" ] }, "group_id": { "description": "Internal group ID of the group in Databricks.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OUTPUT_ONLY" ] @@ -28064,11 +28378,11 @@ "group": { "description": "Required. Group to be updated in \u003cDatabricks\u003e", "ref": "iamv2.Group", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" }, "update_mask": { "description": "Optional. The list of fields to update.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -28077,11 +28391,11 @@ "group": { "description": "Required. Group to be updated in \u003cDatabricks\u003e", "ref": "iamv2.Group", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" }, "update_mask": { "description": "Optional. The list of fields to update.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -28090,11 +28404,11 @@ "service_principal": { "description": "Required. Service principal to be updated in \u003cDatabricks\u003e", "ref": "iamv2.ServicePrincipal", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" }, "update_mask": { "description": "Optional. The list of fields to update.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -28103,11 +28417,11 @@ "service_principal": { "description": "Required. Service Principal to be updated in \u003cDatabricks\u003e", "ref": "iamv2.ServicePrincipal", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" }, "update_mask": { "description": "Optional. The list of fields to update.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -28115,12 +28429,12 @@ "fields": { "update_mask": { "description": "Optional. The list of fields to update.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" }, "user": { "description": "Required. User to be updated in \u003cDatabricks\u003e", "ref": "iamv2.User", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -28128,12 +28442,12 @@ "fields": { "update_mask": { "description": "Optional. The list of fields to update.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" }, "user": { "description": "Required. User to be updated in \u003cDatabricks\u003e", "ref": "iamv2.User", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -28167,12 +28481,12 @@ "fields": { "update_mask": { "description": "Required. The list of fields to update.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" }, "workspace_assignment": { "description": "Required. Workspace assignment to be updated in \u003cDatabricks\u003e.", "ref": "iamv2.WorkspaceAssignment", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -28180,12 +28494,12 @@ "fields": { "update_mask": { "description": "Required. The list of fields to update.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" }, "workspace_assignment": { "description": "Required. Workspace assignment to be updated in \u003cDatabricks\u003e.", "ref": "iamv2.WorkspaceAssignment", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -28193,12 +28507,12 @@ "fields": { "update_mask": { "description": "Required. The list of fields to update.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" }, "workspace_identity_detail": { "description": "Required. Workspace identity detail to be updated in \u003cDatabricks\u003e.", "ref": "iamv2.WorkspaceIdentityDetail", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" } } }, @@ -28342,14 +28656,14 @@ "fields": { "account_id": { "description": "The account ID parent of the workspace where the principal is assigned", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OUTPUT_ONLY" ] }, "effective_entitlements": { "description": "Every entitlement the principal holds in this workspace, whether granted directly or through\ngroup membership. Get responses populate this field. List responses leave it empty.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OUTPUT_ONLY", "UNORDERED_LIST" @@ -28357,7 +28671,7 @@ }, "entitlements": { "description": "Entitlements granted directly to the principal on this workspace. This is the only\nclient-settable field. Create and update manage exactly this set, including entitlements the\nprincipal also holds through a group.\nList responses leave this field empty. Get a single principal to read its entitlements.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL", "UNORDERED_LIST" @@ -28365,19 +28679,19 @@ }, "principal_id": { "description": "The internal ID of the principal (user/sp/group) in Databricks.", - "launch_stage": "PRIVATE_PREVIEW" + "launch_stage": "PUBLIC_BETA" }, "principal_type": { "description": "The type of the principal (user/service principal/group) that is assigned.", "ref": "iamv2.PrincipalType", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OUTPUT_ONLY" ] }, "workspace_id": { "description": "The workspace ID where the principal is assigned.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL", "OUTPUT_ONLY" @@ -28438,14 +28752,14 @@ "assignment_type": { "description": "The type of assignment the principal has to the workspace (direct or indirect).", "ref": "iamv2.WorkspaceIdentityDetailAssignmentType", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OUTPUT_ONLY" ] }, "principal_id": { "description": "The internal ID of the principal (user/sp/group) in Databricks.", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OUTPUT_ONLY" ] @@ -28453,7 +28767,7 @@ "principal_type": { "description": "The type of the principal (user/service principal/group).", "ref": "iamv2.PrincipalType", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OUTPUT_ONLY" ] @@ -28461,7 +28775,7 @@ "workspace_identity_status": { "description": "The activity status of an identity in a Databricks workspace.", "ref": "iamv2.State", - "launch_stage": "PRIVATE_PREVIEW", + "launch_stage": "PUBLIC_BETA", "behaviors": [ "OPTIONAL" ] @@ -28475,8 +28789,8 @@ "INDIRECT" ], "enum_launch_stages": { - "DIRECT": "PRIVATE_PREVIEW", - "INDIRECT": "PRIVATE_PREVIEW" + "DIRECT": "PUBLIC_BETA", + "INDIRECT": "PUBLIC_BETA" } }, "iamv2.WorkspacePermission": { @@ -28585,6 +28899,10 @@ "description": "The alert_id is the canonical identifier of the alert.", "launch_stage": "PUBLIC_PREVIEW" }, + "parameters": { + "description": "Per-run parameter overrides, keyed by parameter name, applied onto the alert's stored\nquery parameters before the query is executed. Only scalar values are supported. Values\nmay reference job parameters with `{{job.parameters.*}}`, which are resolved before the\ntask runs. An override whose key does not match a stored parameter fails the task run.\nLimited to 10000 characters when serialized as JSON; keys must be 1-100 characters and\ncontain only letters, digits, underscores, dashes, and periods.", + "launch_stage": "PRIVATE_PREVIEW" + }, "subscribers": { "description": "The subscribers receive alert evaluation result notifications after the alert task is completed.\nThe number of subscriptions is limited to 100.", "launch_stage": "PUBLIC_PREVIEW" @@ -29111,6 +29429,11 @@ }, "jobs.Continuous": { "fields": { + "maintenance_window": { + "description": "Defines when platform-initiated maintenance may run for this job. If unspecified, maintenance may run at any time.", + "ref": "jobs.MaintenanceWindow", + "launch_stage": "PRIVATE_PREVIEW" + }, "pause_status": { "description": "Indicate whether the continuous execution of the job is paused or not. Defaults to UNPAUSED.", "ref": "jobs.PauseStatus", @@ -29126,6 +29449,11 @@ "jobs.ContinuousTriggerConfiguration": { "description": "Continuous trigger. Stripped-down counterpart to `ContinuousSettings`: `pause_status` is owned by the enclosing\n`TriggerConfiguration` and intentionally omitted here.", "fields": { + "maintenance_window": { + "description": "Defines when platform-initiated maintenance may run for this trigger. If unspecified,\nmaintenance may run at any time.", + "ref": "jobs.MaintenanceWindow", + "launch_stage": "PRIVATE_PREVIEW" + }, "task_retry_mode": { "description": "Whether the continuous job applies task-level retries. Defaults to NEVER.", "ref": "jobs.TaskRetryMode", @@ -29157,7 +29485,7 @@ "launch_stage": "PUBLIC_PREVIEW" }, "continuous": { - "description": "An optional continuous property for this job. The continuous property will ensure that there is always one run executing. Only one of `schedule` and `continuous` can be used.", + "description": "An optional continuous property for this job. The continuous property will ensure that there is always one run executing. Only one of `schedule` and `continuous` can be used.\n\nPipelines started by a continuous job also run continuously, regardless of their own pipeline mode setting.", "ref": "jobs.Continuous", "launch_stage": "GA" }, @@ -29363,6 +29691,27 @@ } } }, + "jobs.DayOfWeek": { + "description": "Days of week that can be referenced by Jobs scheduling settings.", + "enum": [ + "MONDAY", + "TUESDAY", + "WEDNESDAY", + "THURSDAY", + "FRIDAY", + "SATURDAY", + "SUNDAY" + ], + "enum_launch_stages": { + "FRIDAY": "PRIVATE_PREVIEW", + "MONDAY": "PRIVATE_PREVIEW", + "SATURDAY": "PRIVATE_PREVIEW", + "SUNDAY": "PRIVATE_PREVIEW", + "THURSDAY": "PRIVATE_PREVIEW", + "TUESDAY": "PRIVATE_PREVIEW", + "WEDNESDAY": "PRIVATE_PREVIEW" + } + }, "jobs.DbtCloudJobRunStep": { "description": "Format of response retrieved from dbt Cloud, for inclusion in output\nDeprecated in favor of DbtPlatformJobRunStep", "fields": { @@ -30287,7 +30636,7 @@ "launch_stage": "PUBLIC_PREVIEW" }, "continuous": { - "description": "An optional continuous property for this job. The continuous property will ensure that there is always one run executing. Only one of `schedule` and `continuous` can be used.", + "description": "An optional continuous property for this job. The continuous property will ensure that there is always one run executing. Only one of `schedule` and `continuous` can be used.\n\nPipelines started by a continuous job also run continuously, regardless of their own pipeline mode setting.", "ref": "jobs.Continuous", "launch_stage": "GA" }, @@ -30646,6 +30995,24 @@ } } }, + "jobs.MaintenanceWindow": { + "description": "A recurring weekly time window during which platform-initiated maintenance is\nallowed to run for a continuous job.", + "fields": { + "day_of_week": { + "description": "The day of week on which maintenance is allowed to happen. This field is required.", + "ref": "jobs.DayOfWeek", + "launch_stage": "PRIVATE_PREVIEW" + }, + "start_hour": { + "description": "An integer between 0 and 23 denoting the start hour for the maintenance window in the 24-hour day.\nPlatform-initiated maintenance is triggered only within a one-hour window starting at this hour.\nThis field is required.", + "launch_stage": "PRIVATE_PREVIEW" + }, + "timezone_id": { + "description": "A Java timezone ID. The maintenance window is resolved with respect to this timezone. See [Java TimeZone](https://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html) for details. This field is required.", + "launch_stage": "PRIVATE_PREVIEW" + } + } + }, "jobs.ModelTriggerConfiguration": { "fields": { "aliases": { @@ -33387,7 +33754,7 @@ } }, "jobs.TriggerConfiguration": { - "description": "A single trigger attached to a job via `JobSettings.triggers`. Exactly one of the trigger-type fields\n(`periodic`, `schedule`, `continuous`, `file_arrival`, `table_update`, `model`) must be set; mutual exclusivity\nis enforced in the API handler rather than via `oneof` so that codegen, validation, and JSON serialization\nacross SDKs and Terraform behave consistently.", + "description": "A single trigger attached to a job via `JobSettings.triggers`. Exactly one of the trigger-type fields\n(`periodic`, `schedule`, `continuous`, `file_arrival`, `table_update`, `model`, `job_completion`) must be set;\nmutual exclusivity is enforced in the API handler rather than via `oneof` so that codegen, validation, and JSON\nserialization across SDKs and Terraform behave consistently.", "fields": { "continuous": { "description": "Continuous trigger configuration.", @@ -33765,7 +34132,10 @@ }, "guidelines": { "description": "Guidelines for answering the question. Optional — examples may be created\nwith just a question; the front-end form does not require guidelines.", - "launch_stage": "PUBLIC_BETA" + "launch_stage": "PUBLIC_BETA", + "behaviors": [ + "OPTIONAL" + ] }, "name": { "description": "Full resource name:\nknowledge-assistants/{knowledge_assistant_id}/examples/{example_id}", @@ -36246,16 +36616,8 @@ } } }, - "ml.ColumnIdentifier": { - "fields": { - "variant_expr_path": { - "description": "String representation of the column name using dot-prefixed path notation. For nested fields, the leaf value is what will be present in materialized tables\nand expected to match at query time. For example, the leaf node of value.trip_details.location_details.pickup_zip is pickup_zip.", - "launch_stage": "PRIVATE_PREVIEW" - } - } - }, "ml.ColumnSelection": { - "description": "A ColumnSelection function, equivalent to the LAST() record of an entity over a lifetime ContinuousWindow", + "description": "A ColumnSelection function, equivalent to the LAST() record of an entity over a lifetime window", "fields": { "column": { "description": "Column name from source to select as the feature value.", @@ -36316,22 +36678,6 @@ } } }, - "ml.ContinuousWindow": { - "description": "Deprecated: use RollingWindow with `delay` instead.", - "fields": { - "offset": { - "description": "The offset of the continuous window (must be non-positive).", - "launch_stage": "PRIVATE_PREVIEW", - "behaviors": [ - "OPTIONAL" - ] - }, - "window_duration": { - "description": "The duration of the continuous window (must be positive).", - "launch_stage": "PRIVATE_PREVIEW" - } - } - }, "ml.CountFunction": { "description": "Computes the count of values.", "fields": { @@ -36780,6 +37126,14 @@ "OPTIONAL" ] }, + "lateness": { + "description": "Completeness timing for this Feature's use of the source. This configuration is part of the\nFeature definition; it does not modify the underlying table or stream.", + "ref": "ml.SourceLateness", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OPTIONAL" + ] + }, "request_source": { "description": "A request-time data source.", "ref": "ml.RequestSource", @@ -37019,14 +37373,6 @@ "OPTIONAL" ] }, - "entity_columns": { - "description": "Deprecated: Use Feature.entity instead. Kept for backwards compatibility.\nThe entity columns of the Delta table.", - "deprecated": true, - "launch_stage": "PRIVATE_PREVIEW", - "behaviors": [ - "OPTIONAL" - ] - }, "filter_condition": { "description": "Single WHERE clause to filter delta table before applying transformations. Will be row-wise evaluated, so should only include conditionals and projections.", "launch_stage": "PRIVATE_PREVIEW", @@ -37038,14 +37384,6 @@ "description": "The full three-part (catalog, schema, table) name of the Delta table.", "launch_stage": "PRIVATE_PREVIEW" }, - "timeseries_column": { - "description": "Deprecated: Use Feature.timeseries_column instead. Kept for backwards compatibility.\nThe timeseries column of the Delta table.", - "deprecated": true, - "launch_stage": "PRIVATE_PREVIEW", - "behaviors": [ - "OPTIONAL" - ] - }, "transformation_sql": { "description": "A single SQL SELECT expression applied after filter_condition.\nShould contains all the columns needed (eg. \"SELECT *, col_a + col_b AS col_c FROM x.y.z WHERE col_a \u003e 0\" would have `transformation_sql` \"*, col_a + col_b AS col_c\")\nIf transformation_sql is not provided, all columns of the delta table are present in the DataSource dataframe.", "launch_stage": "PRIVATE_PREVIEW", @@ -37296,14 +37634,6 @@ "OPTIONAL" ] }, - "filter_condition": { - "description": "Deprecated: Use DeltaTableSource.filter_condition or KafkaSource.filter_condition instead. Kept for backwards compatibility.\nThe filter condition applied to the source data before aggregation.", - "deprecated": true, - "launch_stage": "PRIVATE_PREVIEW", - "behaviors": [ - "OPTIONAL" - ] - }, "full_name": { "description": "The full three-part name (catalog, schema, name) of the feature. This is the\nfeature's resource identifier; the catalog_name, schema_name, and name fields\nbelow are OUTPUT_ONLY decomposed views of this value.", "launch_stage": "PRIVATE_PREVIEW", @@ -37319,15 +37649,6 @@ "IMMUTABLE" ] }, - "inputs": { - "description": "Deprecated: Use AggregationFunction.inputs instead. Kept for backwards compatibility.\nThe input columns from which the feature is computed.", - "deprecated": true, - "launch_stage": "PRIVATE_PREVIEW", - "behaviors": [ - "IMMUTABLE", - "OPTIONAL" - ] - }, "lineage_context": { "description": "Lineage context information for this feature.\nWARNING: This field is primarily intended for internal use by Databricks systems and\nis automatically populated when features are created through Databricks notebooks or jobs.\nUsers should not manually set this field as incorrect values may lead to inaccurate lineage tracking or unexpected behavior.\nThis field will be set by feature-engineering client and should be left unset by SDK and terraform users.", "ref": "ml.LineageContext", @@ -37358,16 +37679,6 @@ "IMMUTABLE" ] }, - "time_window": { - "description": "Deprecated: Use Function.aggregation_function.time_window instead. Kept for backwards compatibility.\nThe time window in which the feature is computed.", - "ref": "ml.TimeWindow", - "deprecated": true, - "launch_stage": "PRIVATE_PREVIEW", - "behaviors": [ - "IMMUTABLE", - "OPTIONAL" - ] - }, "timeseries_column": { "description": "Column recording time, used for point-in-time joins, backfills, and aggregations.", "ref": "ml.TimeseriesColumn", @@ -37600,72 +37911,9 @@ "behaviors": [ "OPTIONAL" ] - }, - "extra_parameters": { - "description": "Deprecated: Use the function oneof with AggregationFunction instead. Kept for backwards compatibility.\nExtra parameters for parameterized functions.", - "deprecated": true, - "launch_stage": "PRIVATE_PREVIEW", - "behaviors": [ - "OPTIONAL" - ] - }, - "function_type": { - "description": "Deprecated: Use the function oneof with AggregationFunction instead. Kept for backwards compatibility.\nThe type of the function.", - "ref": "ml.FunctionFunctionType", - "deprecated": true, - "launch_stage": "PRIVATE_PREVIEW", - "behaviors": [ - "OPTIONAL" - ] - } - } - }, - "ml.FunctionExtraParameter": { - "description": "Deprecated: Use typed fields on function-specific messages (e.g. ApproxPercentileFunction.percentile)\nor AggregationFunction.ExtraParameter instead. Kept for backwards compatibility.", - "fields": { - "key": { - "description": "The name of the parameter.", - "launch_stage": "PRIVATE_PREVIEW" - }, - "value": { - "description": "The value of the parameter.", - "launch_stage": "PRIVATE_PREVIEW" } } }, - "ml.FunctionFunctionType": { - "description": "Deprecated: Use the function-specific messages in AggregationFunction.function_type oneof instead. Kept for backwards compatibility.", - "enum": [ - "AVG", - "COUNT", - "SUM", - "MIN", - "MAX", - "FIRST", - "LAST", - "APPROX_COUNT_DISTINCT", - "APPROX_PERCENTILE", - "STDDEV_POP", - "STDDEV_SAMP", - "VAR_POP", - "VAR_SAMP" - ], - "enum_launch_stages": { - "APPROX_COUNT_DISTINCT": "PRIVATE_PREVIEW", - "APPROX_PERCENTILE": "PRIVATE_PREVIEW", - "AVG": "PRIVATE_PREVIEW", - "COUNT": "PRIVATE_PREVIEW", - "FIRST": "PRIVATE_PREVIEW", - "LAST": "PRIVATE_PREVIEW", - "MAX": "PRIVATE_PREVIEW", - "MIN": "PRIVATE_PREVIEW", - "STDDEV_POP": "PRIVATE_PREVIEW", - "STDDEV_SAMP": "PRIVATE_PREVIEW", - "SUM": "PRIVATE_PREVIEW", - "VAR_POP": "PRIVATE_PREVIEW", - "VAR_SAMP": "PRIVATE_PREVIEW" - } - }, "ml.GetByNameRequest": { "fields": { "experiment_name": { @@ -38098,14 +38346,6 @@ }, "ml.KafkaSource": { "fields": { - "entity_column_identifiers": { - "description": "Deprecated: Use Feature.entity instead. Kept for backwards compatibility.\nThe entity column identifiers of the Kafka source.", - "deprecated": true, - "launch_stage": "PRIVATE_PREVIEW", - "behaviors": [ - "OPTIONAL" - ] - }, "filter_condition": { "description": "The filter condition applied to the source data before aggregation.", "launch_stage": "PRIVATE_PREVIEW", @@ -38116,15 +38356,6 @@ "name": { "description": "Name of the Kafka source, used to identify it. This is used to look up the corresponding KafkaConfig object. Can be distinct from topic name.", "launch_stage": "PRIVATE_PREVIEW" - }, - "timeseries_column_identifier": { - "description": "Deprecated: Use Feature.timeseries_column instead. Kept for backwards compatibility.\nThe timeseries column identifier of the Kafka source.", - "ref": "ml.ColumnIdentifier", - "deprecated": true, - "launch_stage": "PRIVATE_PREVIEW", - "behaviors": [ - "OPTIONAL" - ] } } }, @@ -38875,13 +39106,6 @@ "ml.MaterializedFeature": { "description": "A materialized feature represents a feature that is continuously computed and stored.", "fields": { - "cron_schedule": { - "description": "The quartz cron expression that defines the schedule of the materialization pipeline. The schedule is evaluated in the UTC timezone.\nHidden from GraphQL: superseded by the `trigger` oneof (cron_schedule_trigger), so not exposed to Catalog Explorer.", - "launch_stage": "PRIVATE_PREVIEW", - "behaviors": [ - "OPTIONAL" - ] - }, "cron_schedule_trigger": { "description": "A cron-based schedule trigger for the materialization pipeline.", "ref": "ml.CronSchedule", @@ -38920,6 +39144,7 @@ "ref": "ml.OfflineStoreConfig", "launch_stage": "PRIVATE_PREVIEW", "behaviors": [ + "IMMUTABLE", "OPTIONAL" ] }, @@ -38928,6 +39153,7 @@ "ref": "ml.OnlineStoreConfig", "launch_stage": "PRIVATE_PREVIEW", "behaviors": [ + "IMMUTABLE", "OPTIONAL" ] }, @@ -39848,7 +40074,7 @@ } }, "ml.RollingWindow": { - "description": "A rolling time window with an optional delay. This is the SQL-spec-aligned\nreplacement for ContinuousWindow: `delay` is the non-negative counterpart\nof the legacy non-positive `ContinuousWindow.offset`.", + "description": "A rolling time window with an optional non-negative delay.", "fields": { "delay": { "description": "Non-negative analytic lag that evaluates the window this far in the past. Use this for timing\nvariations unrelated to source lateness, such as a 30-day count as of one week ago. If unset,\nthe analytic lag is zero. It composes with source.lateness when both are set.", @@ -40456,6 +40682,20 @@ "ml.SetTagResponse": {}, "ml.SlidingWindow": { "fields": { + "delay": { + "description": "Non-negative analytic lag that evaluates the window this far in the past. Use this for timing\nvariations unrelated to source lateness, such as a 30-day count as of one week ago. If unset,\nthe analytic lag is zero. It composes with source.lateness when both are set.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OPTIONAL" + ] + }, + "offset": { + "description": "Non-negative phase shift from the default midnight UTC alignment. For example, offset=22h on\na 24h slide produces boundaries at 22:00 UTC (17:00 New York in standard time) instead of\nmidnight UTC. If unset, the offset is zero. Must be shorter than slide_duration (and therefore\nwindow_duration).", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OPTIONAL" + ] + }, "slide_duration": { "description": "The slide duration (interval by which windows advance, must be positive and less than duration).", "launch_stage": "PRIVATE_PREVIEW" @@ -40469,6 +40709,18 @@ } } }, + "ml.SourceLateness": { + "description": "Configures when event-time data from this source is considered complete for a Feature.", + "fields": { + "settling_delay": { + "description": "Non-negative time to wait after a window ends before treating its source data as complete.\nTraining shifts the eligible evaluation time backwards by this duration so it does not join\ndata that would still have been settling online. Materialization waits for the duration to\nelapse before publishing the window. If unset, source data is considered settled immediately.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OPTIONAL" + ] + } + } + }, "ml.Status": { "description": "The status of the model version. Valid values are:\n* `PENDING_REGISTRATION`: Request to register a new model version is pending as server performs background tasks.\n\n* `FAILED_REGISTRATION`: Request to register a new model version has failed.\n\n* `READY`: Model version is ready for use.", "enum": [ @@ -40788,14 +41040,6 @@ }, "ml.TimeWindow": { "fields": { - "continuous": { - "ref": "ml.ContinuousWindow", - "deprecated": true, - "launch_stage": "PRIVATE_PREVIEW", - "behaviors": [ - "OPTIONAL" - ] - }, "rolling": { "ref": "ml.RollingWindow", "launch_stage": "PRIVATE_PREVIEW", @@ -40818,6 +41062,13 @@ "OPTIONAL" ] }, + "start_time": { + "description": "Earliest event-time boundary at which the Feature may emit an output. This gates outputs, not\nthe historical inputs read by a window. For example, a 365-day window with\nstart_time=2026-01-01 begins emitting partial-window values on that date instead of waiting\nfor 365 days of data; a lifetime window produces no output before start_time. If unset,\ntumbling and fixed-duration sliding windows first emit at an offset-aligned boundary after a\nfull window can be formed. If unset, lifetime sliding windows and rolling windows emit as soon as\neligible source data exists.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OPTIONAL" + ] + }, "tumbling": { "ref": "ml.TumblingWindow", "launch_stage": "PRIVATE_PREVIEW", @@ -40896,6 +41147,20 @@ }, "ml.TumblingWindow": { "fields": { + "delay": { + "description": "Non-negative analytic lag that evaluates the window this far in the past. Use this for timing\nvariations unrelated to source lateness, such as a 30-day count as of one week ago. If unset,\nthe analytic lag is zero. It composes with source.lateness when both are set.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OPTIONAL" + ] + }, + "offset": { + "description": "Non-negative phase shift from the default midnight UTC alignment. For example, offset=22h on\na 24h window produces boundaries at 22:00 UTC (17:00 New York in standard time) instead of\nmidnight UTC. If unset, the offset is zero. Must be shorter than window_duration.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OPTIONAL" + ] + }, "window_duration": { "description": "The duration of each tumbling window (non-overlapping, fixed-duration windows).", "launch_stage": "PRIVATE_PREVIEW" @@ -42145,7 +42410,8 @@ "launch_stage": "GA" }, "continuous": { - "description": "Whether the pipeline is continuous or triggered. This replaces `trigger`.", + "description": "Whether the pipeline is continuous or triggered. This replaces `trigger`.\n\nDeprecated: wrap the pipeline in a continuous job instead, which also lets you take advantage\nof job-level settings such as performance mode. When the pipeline is started by a continuous\njob, the job's setting takes precedence and this field is ignored.", + "deprecated": true, "launch_stage": "GA" }, "deployment": { @@ -42325,6 +42591,10 @@ "ref": "pipelines.OutlookOptions", "launch_stage": "PRIVATE_PREVIEW" }, + "rabbitmq_options": { + "ref": "pipelines.RabbitmqOptions", + "launch_stage": "PUBLIC_BETA" + }, "reddit_ads_options": { "ref": "pipelines.RedditAdsOptions", "launch_stage": "PRIVATE_PREVIEW" @@ -42385,7 +42655,8 @@ "launch_stage": "GA" }, "continuous": { - "description": "Whether the pipeline is continuous or triggered. This replaces `trigger`.", + "description": "Whether the pipeline is continuous or triggered. This replaces `trigger`.\n\nDeprecated: wrap the pipeline in a continuous job instead, which also lets you take advantage\nof job-level settings such as performance mode. When the pipeline is started by a continuous\njob, the job's setting takes precedence and this field is ignored.", + "deprecated": true, "launch_stage": "GA" }, "deployment": { @@ -42625,7 +42896,8 @@ "launch_stage": "GA" }, "continuous": { - "description": "Whether the pipeline is continuous or triggered. This replaces `trigger`.", + "description": "Whether the pipeline is continuous or triggered. This replaces `trigger`.\n\nDeprecated: wrap the pipeline in a continuous job instead, which also lets you take advantage\nof job-level settings such as performance mode. When the pipeline is started by a continuous\njob, the job's setting takes precedence and this field is ignored.", + "deprecated": true, "launch_stage": "GA" }, "deployment": { @@ -43278,6 +43550,7 @@ "CONFLUENCE", "META_MARKETING", "ZENDESK", + "RABBITMQ", "FOREIGN_CATALOG" ], "enum_launch_stages": { @@ -43294,6 +43567,7 @@ "NETSUITE": "PUBLIC_PREVIEW", "ORACLE": "PUBLIC_PREVIEW", "POSTGRESQL": "PUBLIC_PREVIEW", + "RABBITMQ": "PUBLIC_BETA", "SALESFORCE": "PUBLIC_PREVIEW", "SERVICENOW": "PUBLIC_PREVIEW", "SHAREPOINT": "PUBLIC_PREVIEW", @@ -43965,7 +44239,7 @@ "launch_stage": "GA" }, "label": { - "description": "A label for the cluster specification, either `default` to configure the default cluster, or `maintenance` to configure the maintenance cluster. This field is optional. The default value is `default`.", + "description": "A label for the cluster specification, either `default` to configure the default cluster settings applied to both the update and maintenance clusters, `updates` to configure the update cluster, or `maintenance` to configure the maintenance cluster. This field is optional. The default value is `default`.", "launch_stage": "GA" }, "node_type_id": { @@ -44203,7 +44477,8 @@ "launch_stage": "GA" }, "continuous": { - "description": "Whether the pipeline is continuous or triggered. This replaces `trigger`.", + "description": "Whether the pipeline is continuous or triggered. This replaces `trigger`.\n\nDeprecated: wrap the pipeline in a continuous job instead, which also lets you take advantage\nof job-level settings such as performance mode. When the pipeline is started by a continuous\njob, the job's setting takes precedence and this field is ignored.", + "deprecated": true, "launch_stage": "GA" }, "deployment": { @@ -44405,7 +44680,7 @@ }, "environment_version": { "description": "The environment version of the serverless Python environment used to execute\ncustomer Python code. Each environment version includes a specific Python\nversion and a curated set of pre-installed libraries with defined versions,\nproviding a stable and reproducible execution environment.\n\nDatabricks supports a three-year lifecycle for each environment version.\nFor available versions and their included packages, see\nhttps://docs.databricks.com/aws/en/release-notes/serverless/environment-version/\n\nThe value should be a string representing the environment version number, for example: `\"4\"`.", - "launch_stage": "PUBLIC_BETA" + "launch_stage": "PUBLIC_PREVIEW" } } }, @@ -44443,6 +44718,15 @@ "LEGACY_PUBLISHING_MODE": "GA" } }, + "pipelines.RabbitmqOptions": { + "description": "RabbitMQ specific options for ingestion.\nPerformance tuning options (consumers_per_task, max_messages_per_fetch, etc.)\nare intentionally not exposed in the public API. The managed connector uses\nsensible defaults internally. These can be added later if user demand arises.", + "fields": { + "queue": { + "description": "(Required) RabbitMQ queue name to consume from.", + "launch_stage": "PUBLIC_BETA" + } + } + }, "pipelines.RedditAdsOptions": { "description": "Reddit Ads specific options for ingestion", "fields": { @@ -44600,7 +44884,7 @@ "launch_stage": "PUBLIC_PREVIEW" }, "source_schema": { - "description": "Schema name in the source database. Currently required; this field will become optional in\nan upcoming release, since some source types (for example streaming / message-bus connectors)\ndo not use it. When that change ships, this field's type in the generated SDKs and CLI will\nchange from required to optional (nullable); clients that assume it is always present should\nhandle its absence.", + "description": "Schema name in the source database. Optional: some source types (for example streaming or\nmessage-bus connectors) do not use it, so it may be absent from a pipeline's definition.\nClients that assume it is always present should handle its absence.", "launch_stage": "PUBLIC_PREVIEW" }, "table_configuration": { @@ -44831,7 +45115,7 @@ "launch_stage": "PUBLIC_PREVIEW" }, "source_table": { - "description": "Table name in the source database. Currently required; this field will become optional in\nan upcoming release, since some source types (for example streaming / message-bus connectors)\ndo not use it. When that change ships, this field's type in the generated SDKs and CLI will\nchange from required to optional (nullable); clients that assume it is always present should\nhandle its absence.", + "description": "Table name in the source database. Optional: some source types (for example streaming or\nmessage-bus connectors) do not use it, so it may be absent from a pipeline's definition.\nClients that assume it is always present should handle its absence.", "launch_stage": "PUBLIC_PREVIEW" }, "table_configuration": { @@ -45352,6 +45636,14 @@ "OPTIONAL" ] }, + "source_snapshot": { + "description": "The snapshot this branch was created from. When set, the branch's data\ncomes from the snapshot rather than a source branch, so source_branch,\nsource_branch_lsn, and source_branch_time must be empty. The snapshot must\nbe AVAILABLE and belong to this branch's project.\nFormat: projects/{project_id}/snapshots/{snapshot_id}", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "IMMUTABLE", + "OPTIONAL" + ] + }, "ttl": { "description": "Relative time-to-live duration. When set, the branch will expire at creation_time + ttl.\nMutually exclusive with `expire_time` and `no_expiry`. When updating, use `spec.expiration` in the update_mask.", "launch_stage": "GA", @@ -45449,6 +45741,13 @@ "OUTPUT_ONLY" ] }, + "source_snapshot": { + "description": "The snapshot this branch was restored from. Set only for branches created by\nrestoring a snapshot; unset for all other branches.\nFormat: projects/{project_id}/snapshots/{snapshot_id}", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, "state_change_time": { "description": "A timestamp indicating when the `current_state` began.", "launch_stage": "GA", @@ -45844,6 +46143,19 @@ } } }, + "postgres.CreateSnapshotRequest": { + "fields": { + "snapshot": { + "description": "The snapshot to create.", + "ref": "postgres.Snapshot", + "launch_stage": "PRIVATE_PREVIEW" + }, + "snapshot_id": { + "description": "Client-chosen ID for the snapshot. It becomes the final segment of the\nsnapshot resource name and cannot be changed after creation.", + "launch_stage": "PRIVATE_PREVIEW" + } + } + }, "postgres.CreateSyncedTableRequest": { "fields": { "synced_table": { @@ -45856,6 +46168,18 @@ } } }, + "postgres.DailySchedule": { + "description": "Take a snapshot once per day, at the configured hour.", + "fields": { + "hour": { + "description": "The hour of the day, in UTC, at which to take the snapshot, in [0, 23].", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OPTIONAL" + ] + } + } + }, "postgres.DataApi": { "description": "DataApi represents the Data API (PostgREST) configuration for a Database.\nAt most one DataApi per database. Create enables Data API, Delete disables it.", "fields": { @@ -46181,6 +46505,27 @@ } } }, + "postgres.DayOfWeek": { + "description": "The day of the week on which a weekly snapshot is taken.", + "enum": [ + "MONDAY", + "TUESDAY", + "WEDNESDAY", + "THURSDAY", + "FRIDAY", + "SATURDAY", + "SUNDAY" + ], + "enum_launch_stages": { + "FRIDAY": "PRIVATE_PREVIEW", + "MONDAY": "PRIVATE_PREVIEW", + "SATURDAY": "PRIVATE_PREVIEW", + "SUNDAY": "PRIVATE_PREVIEW", + "THURSDAY": "PRIVATE_PREVIEW", + "TUESDAY": "PRIVATE_PREVIEW", + "WEDNESDAY": "PRIVATE_PREVIEW" + } + }, "postgres.DeleteBranchRequest": { "fields": { "purge": { @@ -46229,6 +46574,7 @@ } } }, + "postgres.DeleteSnapshotRequest": {}, "postgres.DeleteSyncedTableRequest": {}, "postgres.DeltaTableSyncInfo": { "fields": { @@ -46776,6 +47122,8 @@ "postgres.GetOperationRequest": {}, "postgres.GetProjectRequest": {}, "postgres.GetRoleRequest": {}, + "postgres.GetSnapshotRequest": {}, + "postgres.GetSnapshotScheduleRequest": {}, "postgres.GetSyncedTableRequest": {}, "postgres.InitialBranchSpec": { "description": "Configuration for the initial default branch created during project creation.", @@ -47062,6 +47410,52 @@ } } }, + "postgres.ListSnapshotsRequest": { + "fields": { + "page_size": { + "description": "Maximum number of snapshots to return per page.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OPTIONAL" + ] + }, + "page_token": { + "description": "Page token from a previous response; omit for the first page.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OPTIONAL" + ] + } + } + }, + "postgres.ListSnapshotsResponse": { + "fields": { + "next_page_token": { + "description": "Token to retrieve the next page; empty if there are no more pages.", + "launch_stage": "PRIVATE_PREVIEW" + }, + "snapshots": { + "description": "The snapshots in the project.", + "launch_stage": "PRIVATE_PREVIEW" + } + } + }, + "postgres.MonthlySchedule": { + "description": "Take a snapshot once per month, on the configured day at the configured hour.", + "fields": { + "day": { + "description": "The day of the month on which to take the snapshot, in [1, 31]. In shorter\nmonths the snapshot is taken on the last day instead (day 31 runs on Feb 28\nor 29, and on Apr 30), so every month gets exactly one snapshot.", + "launch_stage": "PRIVATE_PREVIEW" + }, + "hour": { + "description": "The hour of the day, in UTC, at which to take the snapshot, in [0, 23].", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OPTIONAL" + ] + } + } + }, "postgres.NewPipelineSpec": { "fields": { "budget_policy_id": { @@ -47697,6 +48091,192 @@ } } }, + "postgres.ScheduleCadence": { + "description": "One cadence at which automatic snapshots are taken.", + "fields": { + "daily_schedule": { + "description": "Take a snapshot once per day.", + "ref": "postgres.DailySchedule", + "launch_stage": "PRIVATE_PREVIEW" + }, + "monthly_schedule": { + "description": "Take a snapshot once per month.", + "ref": "postgres.MonthlySchedule", + "launch_stage": "PRIVATE_PREVIEW" + }, + "retention": { + "description": "How long snapshots from this cadence are kept before automatic deletion.\nMust be at least 1 hour. Applied when a snapshot is taken; not retroactive,\nso changing it affects only later snapshots.", + "launch_stage": "PRIVATE_PREVIEW" + }, + "weekly_schedule": { + "description": "Take a snapshot once per week.", + "ref": "postgres.WeeklySchedule", + "launch_stage": "PRIVATE_PREVIEW" + } + } + }, + "postgres.Snapshot": { + "description": "An immutable, point-in-time copy of a branch's data within a project. It\nremains available after the source branch is deleted.", + "fields": { + "create_time": { + "description": "When the snapshot was created.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "name": { + "description": "The resource name of the snapshot.\nFormat: projects/{project_id}/snapshots/{snapshot_id}", + "launch_stage": "PRIVATE_PREVIEW" + }, + "snapshot_id": { + "description": "The user-chosen ID; the final segment of `name`.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "spec": { + "description": "Client-provided configuration of the snapshot.", + "ref": "postgres.SnapshotSpec", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OPTIONAL" + ] + }, + "status": { + "description": "Server-observed state of the snapshot.", + "ref": "postgres.SnapshotStatus", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "uid": { + "description": "Unique system-generated ID for the snapshot.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OUTPUT_ONLY" + ] + } + } + }, + "postgres.SnapshotOperationMetadata": { + "description": "Metadata for the long-running snapshot Create and Delete operations." + }, + "postgres.SnapshotSchedule": { + "description": "The automatic snapshot cadences for a branch. There is exactly one schedule\nper branch (singleton); it is configured in place, not created or deleted.\n\nName: projects/{project_id}/branches/{branch_id}/snapshot-schedule", + "fields": { + "name": { + "description": "The resource name of the branch's snapshot schedule.\nFormat: projects/{project_id}/branches/{branch_id}/snapshot-schedule", + "launch_stage": "PRIVATE_PREVIEW" + }, + "schedule": { + "description": "The cadences at which automatic snapshots are taken. Update replaces the\nwhole set; an empty set disables automatic snapshots. Order is not\nsignificant. When several cadences fire together, one snapshot is taken,\nretained for the longest of their retentions.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OPTIONAL", + "UNORDERED_LIST" + ] + } + } + }, + "postgres.SnapshotScheduleOperationMetadata": { + "description": "Metadata for the long-running snapshot schedule Update operation." + }, + "postgres.SnapshotSpec": { + "description": "Client-provided configuration of the snapshot.", + "fields": { + "expire_time": { + "description": "Absolute time at which the snapshot is deleted.\nMutually exclusive with `ttl` and `no_expiry`.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "IMMUTABLE", + "OPTIONAL" + ] + }, + "no_expiry": { + "description": "If true, the snapshot never expires.\nMutually exclusive with `ttl` and `expire_time`.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "IMMUTABLE", + "OPTIONAL" + ] + }, + "source_branch": { + "description": "The source branch to snapshot.\nFormat: projects/{project_id}/branches/{branch_id}", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "IMMUTABLE" + ] + }, + "source_branch_lsn": { + "description": "LSN to snapshot from, e.g. `16/B374D848`.\nMutually exclusive with `source_branch_time`.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "IMMUTABLE", + "OPTIONAL" + ] + }, + "source_branch_time": { + "description": "Timestamp to snapshot from.\nMutually exclusive with `source_branch_lsn`.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "IMMUTABLE", + "OPTIONAL" + ] + }, + "ttl": { + "description": "Time-to-live. The snapshot expires this long after it is created.\nMutually exclusive with `expire_time` and `no_expiry`. Reads report the\nresolved absolute `expire_time` instead.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "IMMUTABLE", + "INPUT_ONLY", + "OPTIONAL" + ] + } + } + }, + "postgres.SnapshotStatus": { + "description": "Server-observed state of a snapshot.", + "fields": { + "diff_size_bytes": { + "description": "Incremental storage size in bytes since the previous snapshot. Unset when\nthe snapshot is not billed on incremental usage.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "expire_time": { + "description": "Absolute time at which the snapshot is deleted.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "full_size_bytes": { + "description": "Full logical size of the snapshot, in bytes.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "no_expiry": { + "description": "True if the snapshot never expires.", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OUTPUT_ONLY" + ] + }, + "source_branch": { + "description": "The source branch the snapshot was taken from.\nFormat: projects/{project_id}/branches/{branch_id}", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OUTPUT_ONLY" + ] + } + } + }, "postgres.SyncedTable": { "fields": { "create_time": { @@ -48172,6 +48752,36 @@ } } }, + "postgres.UpdateSnapshotScheduleRequest": { + "fields": { + "snapshot_schedule": { + "description": "The snapshot schedule to set. Its `name` identifies the branch.\nFormat: projects/{project_id}/branches/{branch_id}/snapshot-schedule", + "ref": "postgres.SnapshotSchedule", + "launch_stage": "PRIVATE_PREVIEW" + }, + "update_mask": { + "description": "Fields to update. The only updatable path is `schedule`, which replaces the\nentire set of cadences.", + "launch_stage": "PRIVATE_PREVIEW" + } + } + }, + "postgres.WeeklySchedule": { + "description": "Take a snapshot once per week, on the configured day at the configured hour.", + "fields": { + "day_of_week": { + "description": "The day of the week on which to take the snapshot.", + "ref": "postgres.DayOfWeek", + "launch_stage": "PRIVATE_PREVIEW" + }, + "hour": { + "description": "The hour of the day, in UTC, at which to take the snapshot, in [0, 23].", + "launch_stage": "PRIVATE_PREVIEW", + "behaviors": [ + "OPTIONAL" + ] + } + } + }, "provisioning.AwsCredentials": { "fields": { "sts_role": { @@ -55340,7 +55950,7 @@ "fields": { "access_policy_type": { "ref": "settingsv2.AibiDashboardEmbeddingAccessPolicyAccessPolicyType", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55354,15 +55964,15 @@ "DENY_ALL_DOMAINS" ], "enum_launch_stages": { - "ALLOW_ALL_DOMAINS": "PUBLIC_PREVIEW", - "ALLOW_APPROVED_DOMAINS": "PUBLIC_PREVIEW", - "DENY_ALL_DOMAINS": "PUBLIC_PREVIEW" + "ALLOW_ALL_DOMAINS": "GA", + "ALLOW_APPROVED_DOMAINS": "GA", + "DENY_ALL_DOMAINS": "GA" } }, "settingsv2.AibiDashboardEmbeddingApprovedDomains": { "fields": { "approved_domains": { - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55382,7 +55992,7 @@ "settingsv2.BooleanMessage": { "fields": { "value": { - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55392,33 +56002,33 @@ "settingsv2.ClusterAutoRestartMessage": { "fields": { "can_toggle": { - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] }, "enabled": { - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] }, "enablement_details": { "ref": "settingsv2.ClusterAutoRestartMessageEnablementDetails", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] }, "maintenance_window": { "ref": "settingsv2.ClusterAutoRestartMessageMaintenanceWindow", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] }, "restart_even_if_no_updates_available": { - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55430,21 +56040,21 @@ "fields": { "forced_for_compliance_mode": { "description": "The feature is force enabled if compliance mode is active", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] }, "unavailable_for_disabled_entitlement": { "description": "The feature is unavailable if the corresponding entitlement disabled (see getShieldEntitlementEnable)", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] }, "unavailable_for_non_enterprise_tier": { "description": "The feature is unavailable if the customer doesn't have enterprise tier", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55455,7 +56065,7 @@ "fields": { "week_day_based_schedule": { "ref": "settingsv2.ClusterAutoRestartMessageMaintenanceWindowWeekDayBasedSchedule", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55473,34 +56083,34 @@ "SUNDAY" ], "enum_launch_stages": { - "FRIDAY": "PUBLIC_PREVIEW", - "MONDAY": "PUBLIC_PREVIEW", - "SATURDAY": "PUBLIC_PREVIEW", - "SUNDAY": "PUBLIC_PREVIEW", - "THURSDAY": "PUBLIC_PREVIEW", - "TUESDAY": "PUBLIC_PREVIEW", - "WEDNESDAY": "PUBLIC_PREVIEW" + "FRIDAY": "GA", + "MONDAY": "GA", + "SATURDAY": "GA", + "SUNDAY": "GA", + "THURSDAY": "GA", + "TUESDAY": "GA", + "WEDNESDAY": "GA" } }, "settingsv2.ClusterAutoRestartMessageMaintenanceWindowWeekDayBasedSchedule": { "fields": { "day_of_week": { "ref": "settingsv2.ClusterAutoRestartMessageMaintenanceWindowDayOfWeek", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] }, "frequency": { "ref": "settingsv2.ClusterAutoRestartMessageMaintenanceWindowWeekDayFrequency", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] }, "window_start_time": { "ref": "settingsv2.ClusterAutoRestartMessageMaintenanceWindowWindowStartTime", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55518,25 +56128,25 @@ "EVERY_WEEK" ], "enum_launch_stages": { - "EVERY_WEEK": "PUBLIC_PREVIEW", - "FIRST_AND_THIRD_OF_MONTH": "PUBLIC_PREVIEW", - "FIRST_OF_MONTH": "PUBLIC_PREVIEW", - "FOURTH_OF_MONTH": "PUBLIC_PREVIEW", - "SECOND_AND_FOURTH_OF_MONTH": "PUBLIC_PREVIEW", - "SECOND_OF_MONTH": "PUBLIC_PREVIEW", - "THIRD_OF_MONTH": "PUBLIC_PREVIEW" + "EVERY_WEEK": "GA", + "FIRST_AND_THIRD_OF_MONTH": "GA", + "FIRST_OF_MONTH": "GA", + "FOURTH_OF_MONTH": "GA", + "SECOND_AND_FOURTH_OF_MONTH": "GA", + "SECOND_OF_MONTH": "GA", + "THIRD_OF_MONTH": "GA" } }, "settingsv2.ClusterAutoRestartMessageMaintenanceWindowWindowStartTime": { "fields": { "hours": { - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] }, "minutes": { - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55575,7 +56185,7 @@ "settingsv2.IntegerMessage": { "fields": { "value": { - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55586,11 +56196,11 @@ "fields": { "page_size": { "description": "The maximum number of settings to return. The service may return fewer than this value.\nIf unspecified, at most 200 settings will be returned.\nThe maximum value is 1000; values above 1000 will be coerced to 1000.", - "launch_stage": "PUBLIC_PREVIEW" + "launch_stage": "GA" }, "page_token": { "description": "A page token, received from a previous `ListAccountSettingsMetadataRequest` call.\nProvide this to retrieve the subsequent page.\n\nWhen paginating, all other parameters provided to `ListAccountSettingsMetadataRequest` must match\nthe call that provided the page token.", - "launch_stage": "PUBLIC_PREVIEW" + "launch_stage": "GA" } } }, @@ -55598,11 +56208,11 @@ "fields": { "next_page_token": { "description": "A token that can be sent as `page_token` to retrieve the next page.\nIf this field is omitted, there are no subsequent pages.", - "launch_stage": "PUBLIC_PREVIEW" + "launch_stage": "GA" }, "settings_metadata": { "description": "List of all settings available via public APIs and their metadata", - "launch_stage": "PUBLIC_PREVIEW" + "launch_stage": "GA" } } }, @@ -55640,11 +56250,11 @@ "fields": { "page_size": { "description": "The maximum number of settings to return. The service may return fewer than this value.\nIf unspecified, at most 200 settings will be returned.\nThe maximum value is 1000; values above 1000 will be coerced to 1000.", - "launch_stage": "PUBLIC_PREVIEW" + "launch_stage": "GA" }, "page_token": { "description": "A page token, received from a previous `ListWorkspaceSettingsMetadataRequest` call.\nProvide this to retrieve the subsequent page.\n\nWhen paginating, all other parameters provided to `ListWorkspaceSettingsMetadataRequest` must match\nthe call that provided the page token.", - "launch_stage": "PUBLIC_PREVIEW" + "launch_stage": "GA" } } }, @@ -55652,11 +56262,11 @@ "fields": { "next_page_token": { "description": "A token that can be sent as `page_token` to retrieve the next page.\nIf this field is omitted, there are no subsequent pages.", - "launch_stage": "PUBLIC_PREVIEW" + "launch_stage": "GA" }, "settings_metadata": { "description": "List of all settings available via public APIs and their metadata", - "launch_stage": "PUBLIC_PREVIEW" + "launch_stage": "GA" } } }, @@ -55674,7 +56284,7 @@ "fields": { "setting": { "ref": "settingsv2.Setting", - "launch_stage": "PUBLIC_PREVIEW" + "launch_stage": "GA" } } }, @@ -55690,7 +56300,7 @@ "fields": { "setting": { "ref": "settingsv2.Setting", - "launch_stage": "PUBLIC_PREVIEW" + "launch_stage": "GA" } } }, @@ -55698,7 +56308,7 @@ "fields": { "value": { "ref": "settingsv2.PersonalComputeMessagePersonalComputeMessageEnum", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55712,8 +56322,8 @@ "DELEGATE" ], "enum_launch_stages": { - "DELEGATE": "PUBLIC_PREVIEW", - "ON": "PUBLIC_PREVIEW" + "DELEGATE": "GA", + "ON": "GA" } }, "settingsv2.PreviewPhase": { @@ -55744,7 +56354,7 @@ }, "status": { "ref": "settingsv2.RestrictWorkspaceAdminsMessageStatus", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55757,8 +56367,8 @@ "RESTRICT_TOKENS_AND_JOB_RUN_AS" ], "enum_launch_stages": { - "ALLOW_ALL": "PUBLIC_PREVIEW", - "RESTRICT_TOKENS_AND_JOB_RUN_AS": "PUBLIC_PREVIEW" + "ALLOW_ALL": "GA", + "RESTRICT_TOKENS_AND_JOB_RUN_AS": "GA" } }, "settingsv2.Setting": { @@ -55766,7 +56376,7 @@ "aibi_dashboard_embedding_access_policy": { "description": "Setting value for aibi_dashboard_embedding_access_policy setting. This is the setting value set by consumers, check effective_aibi_dashboard_embedding_access_policy for final setting value.", "ref": "settingsv2.AibiDashboardEmbeddingAccessPolicy", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55774,7 +56384,7 @@ "aibi_dashboard_embedding_approved_domains": { "description": "Setting value for aibi_dashboard_embedding_approved_domains setting. This is the setting value set by consumers, check effective_aibi_dashboard_embedding_approved_domains for final setting value.", "ref": "settingsv2.AibiDashboardEmbeddingApprovedDomains", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55790,7 +56400,7 @@ "automatic_cluster_update_workspace": { "description": "Setting value for automatic_cluster_update_workspace setting. This is the setting value set by consumers, check effective_automatic_cluster_update_workspace for final setting value.", "ref": "settingsv2.ClusterAutoRestartMessage", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55798,7 +56408,7 @@ "boolean_val": { "description": "Setting value for boolean type setting. This is the setting value set by consumers, check effective_boolean_val for final setting value.", "ref": "settingsv2.BooleanMessage", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55814,7 +56424,7 @@ "effective_aibi_dashboard_embedding_access_policy": { "description": "Effective setting value for aibi_dashboard_embedding_access_policy setting. This is the final effective value of setting. To set a value use aibi_dashboard_embedding_access_policy.", "ref": "settingsv2.AibiDashboardEmbeddingAccessPolicy", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55822,7 +56432,7 @@ "effective_aibi_dashboard_embedding_approved_domains": { "description": "Effective setting value for aibi_dashboard_embedding_approved_domains setting. This is the final effective value of setting. To set a value use aibi_dashboard_embedding_approved_domains.", "ref": "settingsv2.AibiDashboardEmbeddingApprovedDomains", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55838,7 +56448,7 @@ "effective_automatic_cluster_update_workspace": { "description": "Effective setting value for automatic_cluster_update_workspace setting. This is the final effective value of setting. To set a value use automatic_cluster_update_workspace.", "ref": "settingsv2.ClusterAutoRestartMessage", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55846,7 +56456,7 @@ "effective_boolean_val": { "description": "Effective setting value for boolean type setting. This is the final effective value of setting. To set a value use boolean_val.", "ref": "settingsv2.BooleanMessage", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OUTPUT_ONLY" ] @@ -55862,7 +56472,7 @@ "effective_integer_val": { "description": "Effective setting value for integer type setting. This is the final effective value of setting. To set a value use integer_val.", "ref": "settingsv2.IntegerMessage", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OUTPUT_ONLY" ] @@ -55878,7 +56488,7 @@ "effective_personal_compute": { "description": "Effective setting value for personal_compute setting. This is the final effective value of setting. To set a value use personal_compute.", "ref": "settingsv2.PersonalComputeMessage", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55886,7 +56496,7 @@ "effective_restrict_workspace_admins": { "description": "Effective setting value for restrict_workspace_admins setting. This is the final effective value of setting. To set a value use restrict_workspace_admins.", "ref": "settingsv2.RestrictWorkspaceAdminsMessage", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55894,7 +56504,7 @@ "effective_string_val": { "description": "Effective setting value for string type setting. This is the final effective value of setting. To set a value use string_val.", "ref": "settingsv2.StringMessage", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OUTPUT_ONLY" ] @@ -55902,14 +56512,14 @@ "integer_val": { "description": "Setting value for integer type setting. This is the setting value set by consumers, check effective_integer_val for final setting value.", "ref": "settingsv2.IntegerMessage", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] }, "name": { "description": "Name of the setting.", - "launch_stage": "PUBLIC_PREVIEW" + "launch_stage": "GA" }, "operational_email_custom_recipient": { "description": "Setting value for operational_email_custom_recipient setting. This is the setting value set by consumers, check effective_operational_email_custom_recipient for final setting value.", @@ -55922,7 +56532,7 @@ "personal_compute": { "description": "Setting value for personal_compute setting. This is the setting value set by consumers, check effective_personal_compute for final setting value.", "ref": "settingsv2.PersonalComputeMessage", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55930,7 +56540,7 @@ "restrict_workspace_admins": { "description": "Setting value for restrict_workspace_admins setting. This is the setting value set by consumers, check effective_restrict_workspace_admins for final setting value.", "ref": "settingsv2.RestrictWorkspaceAdminsMessage", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55938,7 +56548,7 @@ "string_val": { "description": "Setting value for string type setting. This is the setting value set by consumers, check effective_string_val for final setting value.", "ref": "settingsv2.StringMessage", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -55949,7 +56559,7 @@ "fields": { "description": { "description": "Setting description for what this setting controls", - "launch_stage": "PUBLIC_PREVIEW" + "launch_stage": "GA" }, "display_name": { "description": "Human-readable display name for the setting or feature preview.\nThis field may be unset if no display name is available.", @@ -55957,11 +56567,11 @@ }, "docs_link": { "description": "Link to databricks documentation for the setting", - "launch_stage": "PUBLIC_PREVIEW" + "launch_stage": "GA" }, "name": { "description": "Name of the setting.", - "launch_stage": "PUBLIC_PREVIEW" + "launch_stage": "GA" }, "preview_phase": { "description": "Preview phase for feature preview settings. This field is not set for non-preview settings.", @@ -55970,7 +56580,7 @@ }, "type": { "description": "Sample message depicting the type of the setting. To set this setting, the value sent must match this type.", - "launch_stage": "PUBLIC_PREVIEW" + "launch_stage": "GA" } } }, @@ -55978,7 +56588,7 @@ "fields": { "value": { "description": "Represents a generic string value.", - "launch_stage": "PUBLIC_PREVIEW", + "launch_stage": "GA", "behaviors": [ "OPTIONAL" ] @@ -57961,21 +58571,21 @@ } }, "sql.AlertStatementParameter": { - "description": "Redash-owned copy of the internal StatementParameter for the external AlertV2 API.\nThe internal `ordinal` and `args` fields are intentionally omitted: the public API\nsupports only flat, named scalar parameters; complex types (ARRAY, MAP, STRUCT) are\nnot supported. This mirrors SEA's public StatementParameter schema, see:\ncmdexec/sql-exec-api/proto/sql_exec_api_service.proto:763-779", + "description": "A named parameter bound to the alert query. Only flat, named scalar parameters are\nsupported; complex types such as ARRAY, MAP, and STRUCT are not.", "fields": { "name": { - "description": "The name of the parameter, referenced in the query as `:name`.", + "description": "The name of the parameter. Reference it in the query text as `:name`. Required, must be\nnon-empty, and must be unique across the alert's parameters.", "launch_stage": "PRIVATE_PREVIEW" }, "type": { - "description": "The SQL data type of the parameter, e.g. STRING, INT, or DATE. Defaults to STRING. This is a\nstring rather than an enum because scalar subtypes such as DECIMAL(10, 4) cannot be enumerated.\nComplex types such as ARRAY, MAP, and STRUCT are not supported.", + "description": "The SQL data type of the parameter, for example `STRING`, `INT`, or `DECIMAL(10, 2)`. If no type is given\nthe type is assumed to be `STRING`. Complex types such as `ARRAY`, `MAP`, and `STRUCT` are not supported.", "launch_stage": "PRIVATE_PREVIEW", "behaviors": [ "OPTIONAL" ] }, "value": { - "description": "The bound value for the parameter, given as a string. If omitted, the value is interpreted as NULL.", + "description": "The value bound to the parameter, represented as a string. If omitted, the value is interpreted as NULL.", "launch_stage": "PRIVATE_PREVIEW", "behaviors": [ "OPTIONAL" @@ -58023,7 +58633,7 @@ "launch_stage": "GA" }, "id": { - "description": "UUID identifying the alert.", + "description": "The canonical identifier of the alert to retrieve information about.", "launch_stage": "GA", "behaviors": [ "OUTPUT_ONLY" @@ -58045,7 +58655,7 @@ ] }, "parameters": { - "description": "Query parameters bound when executing the alert query, referenced in the\nquery text with `:name` syntax. Static values only.", + "description": "A list of parameters to pass into the alert SQL query statement containing parameter markers. Static values only.\n\nReference a parameter in the query text as `:name`. Each parameter must have a unique, non-empty name.\nEach parameter consists of a name, a value, and optionally a type. To represent a NULL\nvalue, the `value` field may be omitted or set to `null` explicitly. If the `type` field\nis omitted, the value is interpreted as a string.\n\nIf the type is given, parameters will be checked for type correctness according\nto the given type. A value is correct if the provided string can be converted to\nthe requested type using the `cast` function. The exact semantics are described in\nthe section [`cast` function](https://docs.databricks.com/sql/language-manual/functions/cast.html) of the SQL language reference.", "launch_stage": "PRIVATE_PREVIEW", "behaviors": [ "OPTIONAL", @@ -73151,7 +73761,7 @@ }, { "name": "id", - "description": "UUID identifying the alert.", + "description": "The canonical identifier of the alert to retrieve information about.", "is_output_only": true, "is_request_body_field": true, "entity": { @@ -73186,7 +73796,7 @@ }, { "name": "parameters", - "description": "Query parameters bound when executing the alert query, referenced in the\nquery text with `:name` syntax. Static values only.", + "description": "A list of parameters to pass into the alert SQL query statement containing parameter markers. Static values only.\n\nReference a parameter in the query text as `:name`. Each parameter must have a unique, non-empty name.\nEach parameter consists of a name, a value, and optionally a type. To represent a NULL\nvalue, the `value` field may be omitted or set to `null` explicitly. If the `type` field\nis omitted, the value is interpreted as a string.\n\nIf the type is given, parameters will be checked for type correctness according\nto the given type. A value is correct if the provided string can be converted to\nthe requested type using the `cast` function. The exact semantics are described in\nthe section [`cast` function](https://docs.databricks.com/sql/language-manual/functions/cast.html) of the SQL language reference.", "is_request_body_field": true, "entity": { "pascal_name": "AlertStatementParameterList", @@ -73586,7 +74196,7 @@ "required_fields": [ { "name": "id", - "description": "UUID identifying the alert.", + "description": "The canonical identifier of the alert to retrieve information about.", "required": true, "is_path": true, "is_output_only": true, @@ -73616,7 +74226,7 @@ "required_in_url_fields": [ { "name": "id", - "description": "UUID identifying the alert.", + "description": "The canonical identifier of the alert to retrieve information about.", "required": true, "is_path": true, "is_output_only": true, @@ -73956,7 +74566,7 @@ }, { "name": "id", - "description": "UUID identifying the alert.", + "description": "The canonical identifier of the alert to retrieve information about.", "required": true, "is_path": true, "is_output_only": true, @@ -74029,7 +74639,7 @@ }, { "name": "id", - "description": "UUID identifying the alert.", + "description": "The canonical identifier of the alert to retrieve information about.", "is_output_only": true, "is_request_body_field": true, "entity": { @@ -74064,7 +74674,7 @@ }, { "name": "parameters", - "description": "Query parameters bound when executing the alert query, referenced in the\nquery text with `:name` syntax. Static values only.", + "description": "A list of parameters to pass into the alert SQL query statement containing parameter markers. Static values only.\n\nReference a parameter in the query text as `:name`. Each parameter must have a unique, non-empty name.\nEach parameter consists of a name, a value, and optionally a type. To represent a NULL\nvalue, the `value` field may be omitted or set to `null` explicitly. If the `type` field\nis omitted, the value is interpreted as a string.\n\nIf the type is given, parameters will be checked for type correctness according\nto the given type. A value is correct if the provided string can be converted to\nthe requested type using the `cast` function. The exact semantics are described in\nthe section [`cast` function](https://docs.databricks.com/sql/language-manual/functions/cast.html) of the SQL language reference.", "is_request_body_field": true, "entity": { "pascal_name": "AlertStatementParameterList", @@ -74140,7 +74750,7 @@ "required_positional_arguments": [ { "name": "id", - "description": "UUID identifying the alert.", + "description": "The canonical identifier of the alert to retrieve information about.", "required": true, "is_path": true, "is_output_only": true, @@ -74865,6 +75475,14 @@ ] } }, + { + "name": "assume_group_id", + "description": "The group whose permissions users assume via Role Authorization for apps in this space. When\nset, user tokens assume the role of this group instead of doing regular obo token downscoping.\nSet only at space creation.", + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, { "name": "create_time", "description": "The creation time of the app space. Formatted timestamp in ISO 6801.", @@ -77503,6 +78121,14 @@ "is_field_mask": true } }, + { + "name": "assume_group_id", + "description": "The group whose permissions users assume via Role Authorization for apps in this space. When\nset, user tokens assume the role of this group instead of doing regular obo token downscoping.\nSet only at space creation.", + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, { "name": "create_time", "description": "The creation time of the app space. Formatted timestamp in ISO 6801.", @@ -80665,7 +81291,7 @@ "required_fields": [ { "name": "deployment", - "description": "The deployment to create. The caller must set `initial_parent_path`. Other fields are ignored\non input and populated by the service.", + "description": "The deployment to create. `initial_parent_path` is required. `display_name`, `target_name`,\n`deployment_mode`, and `workspace_info` may be set; every other field is assigned by the\nservice and ignored on input.", "required": true, "is_request_body_field": true, "entity": { @@ -80677,7 +81303,7 @@ "required_request_body_fields": [ { "name": "deployment", - "description": "The deployment to create. The caller must set `initial_parent_path`. Other fields are ignored\non input and populated by the service.", + "description": "The deployment to create. `initial_parent_path` is required. `display_name`, `target_name`,\n`deployment_mode`, and `workspace_info` may be set; every other field is assigned by the\nservice and ignored on input.", "required": true, "is_request_body_field": true, "entity": { @@ -80689,7 +81315,7 @@ }, "request_body_field": { "name": "deployment", - "description": "The deployment to create. The caller must set `initial_parent_path`. Other fields are ignored\non input and populated by the service.", + "description": "The deployment to create. `initial_parent_path` is required. `display_name`, `target_name`,\n`deployment_mode`, and `workspace_info` may be set; every other field is assigned by the\nservice and ignored on input.", "required": true, "is_request_body_field": true, "entity": { @@ -80704,7 +81330,7 @@ "all_fields": [ { "name": "deployment", - "description": "The deployment to create. The caller must set `initial_parent_path`. Other fields are ignored\non input and populated by the service.", + "description": "The deployment to create. `initial_parent_path` is required. `display_name`, `target_name`,\n`deployment_mode`, and `workspace_info` may be set; every other field is assigned by the\nservice and ignored on input.", "required": true, "is_request_body_field": true, "entity": { @@ -80733,8 +81359,7 @@ }, { "name": "deployment_mode", - "description": "Bundle target deployment mode (development or production), derived from the\nmost recent version's mode.", - "is_output_only": true, + "description": "Bundle target deployment mode (development or production).", "is_request_body_field": true, "entity": { "pascal_name": "DeploymentMode", @@ -80769,8 +81394,7 @@ }, { "name": "display_name", - "description": "Human-readable name for the deployment, up to 256 characters. Output only: clients update it\nby setting `display_name` when creating a version.", - "is_output_only": true, + "description": "Human-readable name for the deployment, up to 256 characters.", "is_request_body_field": true, "entity": { "is_string": true @@ -80847,8 +81471,7 @@ }, { "name": "target_name", - "description": "The bundle target name associated with this deployment. Output only: it is\ndenormalized from the latest version, not set directly on the deployment.", - "is_output_only": true, + "description": "The bundle target name associated with this deployment.", "is_request_body_field": true, "entity": { "is_string": true @@ -80875,8 +81498,7 @@ }, { "name": "workspace_info", - "description": "Workspace location of the deployment, derived from the latest version.", - "is_output_only": true, + "description": "Workspace location of the deployment.", "is_request_body_field": true, "is_optional_object": true, "entity": { @@ -81291,6 +81913,18 @@ "is_string": true } }, + { + "name": "operations", + "description": "The full operation plan for this version: one PENDING operation per entry,\nrecorded in the same transaction. Input only -- supplied on create and never\nreturned by create/get/list; read the recorded operations via ListOperations.", + "is_request_body_field": true, + "entity": { + "pascal_name": "StagedOperationList", + "array_value": { + "pascal_name": "StagedOperation", + "is_object": true + } + } + }, { "name": "previous_version_id", "description": "The version_id this version was created on top of — the deployment's\nmost recent version at creation time. Leave unset when creating the\nfirst version (the deployment has no prior versions). Set by the\nclient on creation and immutable thereafter.\n\nActs as an optimistic-concurrency precondition: the server requires\nit to equal the deployment's current most-recent version (and to be\nunset when the deployment has no versions) and returns\n`INVALID_PARAMETER_VALUE` on mismatch, so a deploy racing against a\nconcurrent deploy is rejected rather than silently overwriting it.", @@ -81671,9 +82305,18 @@ { "content": "DEPLOYMENT_RESOURCE_TYPE_EXTERNAL_LOCATION" }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_GENIE_SPACE" + }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_INSTANCE_POOL" + }, { "content": "DEPLOYMENT_RESOURCE_TYPE_JOB" }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_JOB_RUN" + }, { "content": "DEPLOYMENT_RESOURCE_TYPE_MODEL" }, @@ -81686,12 +82329,24 @@ { "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_BRANCH" }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_CATALOG" + }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_DATABASE" + }, { "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_ENDPOINT" }, { "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_PROJECT" }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_ROLE" + }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_SYNCED_TABLE" + }, { "content": "DEPLOYMENT_RESOURCE_TYPE_QUALITY_MONITOR" }, @@ -81710,6 +82365,12 @@ { "content": "DEPLOYMENT_RESOURCE_TYPE_SYNCED_DATABASE_TABLE" }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_VECTOR_SEARCH_ENDPOINT" + }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_VECTOR_SEARCH_INDEX" + }, { "content": "DEPLOYMENT_RESOURCE_TYPE_VOLUME" } @@ -81753,9 +82414,18 @@ { "content": "DEPLOYMENT_RESOURCE_TYPE_EXTERNAL_LOCATION" }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_GENIE_SPACE" + }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_INSTANCE_POOL" + }, { "content": "DEPLOYMENT_RESOURCE_TYPE_JOB" }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_JOB_RUN" + }, { "content": "DEPLOYMENT_RESOURCE_TYPE_MODEL" }, @@ -81768,12 +82438,24 @@ { "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_BRANCH" }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_CATALOG" + }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_DATABASE" + }, { "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_ENDPOINT" }, { "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_PROJECT" }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_ROLE" + }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_SYNCED_TABLE" + }, { "content": "DEPLOYMENT_RESOURCE_TYPE_QUALITY_MONITOR" }, @@ -81792,6 +82474,12 @@ { "content": "DEPLOYMENT_RESOURCE_TYPE_SYNCED_DATABASE_TABLE" }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_VECTOR_SEARCH_ENDPOINT" + }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_VECTOR_SEARCH_INDEX" + }, { "content": "DEPLOYMENT_RESOURCE_TYPE_VOLUME" } @@ -82323,6 +83011,314 @@ } } }, + { + "name": "UpdateDeployment", + "description": "Updates a deployment.", + "summary": "Update a deployment.", + "path": "/api/2.0/bundle/{name=deployments/*}", + "can_use_json": true, + "must_use_json": true, + "is_json_only": true, + "is_hidden_cli": true, + "has_required_positional_arguments": true, + "launch_stage": "PRIVATE_PREVIEW", + "cli_launch_stage_display": "Private Preview", + "request": { + "pascal_name": "UpdateDeploymentRequest", + "is_object": true, + "has_field_mask": true, + "has_required_request_body_fields": true, + "required_fields": [ + { + "name": "name", + "description": "Resource name of the deployment.\nFormat: deployments/{deployment_id}", + "required": true, + "is_path": true, + "is_output_only": true, + "entity": { + "is_string": true + } + }, + { + "name": "deployment", + "description": "The deployment to update. Its `name` selects the deployment; the fields\nnamed in `update_mask` carry the new values. All other fields are ignored.", + "required": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "Deployment", + "is_object": true + } + }, + { + "name": "update_mask", + "description": "The fields to update; supported paths are `display_name`, `deployment_mode`, `target_name`,\nand `workspace_info`. An empty mask or any other path returns INVALID_PARAMETER_VALUE.", + "required": true, + "is_query": true, + "entity": { + "is_field_mask": true + } + } + ], + "required_in_url_fields": [ + { + "name": "name", + "description": "Resource name of the deployment.\nFormat: deployments/{deployment_id}", + "required": true, + "is_path": true, + "is_output_only": true, + "entity": { + "is_string": true + } + }, + { + "name": "update_mask", + "description": "The fields to update; supported paths are `display_name`, `deployment_mode`, `target_name`,\nand `workspace_info`. An empty mask or any other path returns INVALID_PARAMETER_VALUE.", + "required": true, + "is_query": true, + "entity": { + "is_field_mask": true + } + } + ], + "required_request_body_fields": [ + { + "name": "deployment", + "description": "The deployment to update. Its `name` selects the deployment; the fields\nnamed in `update_mask` carry the new values. All other fields are ignored.", + "required": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "Deployment", + "is_object": true + } + } + ] + }, + "request_body_field": { + "name": "deployment", + "description": "The deployment to update. Its `name` selects the deployment; the fields\nnamed in `update_mask` carry the new values. All other fields are ignored.", + "required": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "Deployment", + "is_object": true + } + }, + "response": { + "pascal_name": "Deployment", + "is_object": true + }, + "all_fields": [ + { + "name": "deployment", + "description": "The deployment to update. Its `name` selects the deployment; the fields\nnamed in `update_mask` carry the new values. All other fields are ignored.", + "required": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "Deployment", + "is_object": true + } + }, + { + "name": "name", + "description": "Resource name of the deployment.\nFormat: deployments/{deployment_id}", + "required": true, + "is_path": true, + "is_output_only": true, + "entity": { + "is_string": true + } + }, + { + "name": "update_mask", + "description": "The fields to update; supported paths are `display_name`, `deployment_mode`, `target_name`,\nand `workspace_info`. An empty mask or any other path returns INVALID_PARAMETER_VALUE.", + "required": true, + "is_query": true, + "entity": { + "is_field_mask": true + } + }, + { + "name": "create_time", + "description": "When the deployment was created.", + "is_output_only": true, + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "is_timestamp": true + } + }, + { + "name": "created_by", + "description": "The user who created the deployment (email or principal name). Empty if authoritative\ndeployment metadata does not identify a creator or the principal cannot be resolved.", + "is_output_only": true, + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "deployment_mode", + "description": "Bundle target deployment mode (development or production).", + "is_request_body_field": true, + "entity": { + "pascal_name": "DeploymentMode", + "enum": [ + { + "content": "DEPLOYMENT_MODE_DEVELOPMENT" + }, + { + "content": "DEPLOYMENT_MODE_PRODUCTION" + } + ] + } + }, + { + "name": "destroy_time", + "description": "When deletion was recorded. Unset if deletion has not been recorded.\nThis response metadata does not determine the deployment's lifecycle status.", + "is_output_only": true, + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "is_timestamp": true + } + }, + { + "name": "destroyed_by", + "description": "The user who destroyed the deployment (email or principal name).\nUnset if the deployment has not been destroyed.", + "is_output_only": true, + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "display_name", + "description": "Human-readable name for the deployment, up to 256 characters.", + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "git_info", + "description": "Git provenance of the deployment's source, derived from the latest version.", + "is_output_only": true, + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "pascal_name": "GitInfo", + "is_object": true + } + }, + { + "name": "initial_parent_path", + "description": "The workspace path of the existing folder where the deployment is initially created. Must be\nabsolute and canonical, with single separators, no `.` or `..` segments, and no trailing slash\nunless the path is `/`. It may contain at most 24 path segments, excluding an optional leading\n`/Workspace` segment. The complete path may contain up to 1,024 characters, and each segment\nmay contain up to 511 characters. This field is input only and is not returned in create, get,\nor list responses.", + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "last_successful_version_id", + "description": "The version_id of the most recent version that completed successfully.\nUnset until a version has completed successfully. Unlike last_version_id,\nit is not advanced when a version fails, so it always points at the last\nknown-good deployment state (or is unset if there has never been one).", + "is_output_only": true, + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "last_version_id", + "description": "The version_id of the most recent deployment version.", + "is_output_only": true, + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "name", + "description": "Resource name of the deployment.\nFormat: deployments/{deployment_id}", + "is_output_only": true, + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "status", + "description": "Current status of the deployment.", + "is_output_only": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "DeploymentStatus", + "enum": [ + { + "content": "DEPLOYMENT_STATUS_ACTIVE" + }, + { + "content": "DEPLOYMENT_STATUS_DELETED" + }, + { + "content": "DEPLOYMENT_STATUS_FAILED" + }, + { + "content": "DEPLOYMENT_STATUS_IN_PROGRESS" + } + ] + } + }, + { + "name": "target_name", + "description": "The bundle target name associated with this deployment.", + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "update_time", + "description": "When the deployment was last updated.", + "is_output_only": true, + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "is_timestamp": true + } + }, + { + "name": "updated_by", + "description": "The user who most recently updated the deployment (email or principal name). Empty if\nauthoritative deployment metadata does not identify a modifier or the principal cannot be\nresolved.", + "is_output_only": true, + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "workspace_info", + "description": "Workspace location of the deployment.", + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "pascal_name": "WorkspaceInfo", + "is_object": true + } + } + ], + "required_positional_arguments": [ + { + "name": "name", + "description": "Resource name of the deployment.\nFormat: deployments/{deployment_id}", + "required": true, + "is_path": true, + "is_output_only": true, + "entity": { + "is_string": true + } + } + ] + }, { "name": "UpdateOperation", "description": "Updates a resource operation's mutable fields.\n\n`state`, `error_message`, `resource_id`, `status`, and `dashboard_metadata`\nmay be updated, independently; `update_mask` must contain only those paths.\nAll other fields are immutable. The update is guarded by an\noptimistic-concurrency check: the caller sets `operation.sequence_id` to the\nvalue it last observed, and the server rejects the update with `ABORTED` if\nthe operation has been modified since. On success the server increments\n`sequence_id`; updates to `state`, `resource_id`, and `dashboard_metadata`\nare mirrored onto the corresponding deployment-level resource. Listing\n`state` in `update_mask` with no value clears it, which removes the\nresource, so a delete that is retried until it succeeds must clear `state`.\nThe parent version must be in progress, and after the update is applied a\nsucceeded operation cannot carry an `error_message`. See the `state` and\n`resource_id` fields for the rest.", @@ -82574,9 +83570,18 @@ { "content": "DEPLOYMENT_RESOURCE_TYPE_EXTERNAL_LOCATION" }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_GENIE_SPACE" + }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_INSTANCE_POOL" + }, { "content": "DEPLOYMENT_RESOURCE_TYPE_JOB" }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_JOB_RUN" + }, { "content": "DEPLOYMENT_RESOURCE_TYPE_MODEL" }, @@ -82589,12 +83594,24 @@ { "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_BRANCH" }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_CATALOG" + }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_DATABASE" + }, { "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_ENDPOINT" }, { "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_PROJECT" }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_ROLE" + }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_POSTGRES_SYNCED_TABLE" + }, { "content": "DEPLOYMENT_RESOURCE_TYPE_QUALITY_MONITOR" }, @@ -82613,6 +83630,12 @@ { "content": "DEPLOYMENT_RESOURCE_TYPE_SYNCED_DATABASE_TABLE" }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_VECTOR_SEARCH_ENDPOINT" + }, + { + "content": "DEPLOYMENT_RESOURCE_TYPE_VECTOR_SEARCH_INDEX" + }, { "content": "DEPLOYMENT_RESOURCE_TYPE_VOLUME" } @@ -82645,6 +83668,9 @@ { "content": "OPERATION_STATUS_FAILED" }, + { + "content": "OPERATION_STATUS_PENDING" + }, { "content": "OPERATION_STATUS_SUCCEEDED" } @@ -88479,7 +89505,7 @@ }, { "name": "total_initial_remote_disk_size", - "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Currently only supported for GCP HYPERDISK_BALANCED disks.", + "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Supported for GCP.", "is_request_body_field": true, "entity": { "is_int": true @@ -89045,7 +90071,7 @@ }, { "name": "total_initial_remote_disk_size", - "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Currently only supported for GCP HYPERDISK_BALANCED disks.", + "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Supported for GCP.", "is_request_body_field": true, "entity": { "is_int": true @@ -119502,14 +120528,6 @@ } } }, - { - "name": "filter_condition", - "description": "Deprecated: Use DeltaTableSource.filter_condition or KafkaSource.filter_condition instead. Kept for backwards compatibility.\nThe filter condition applied to the source data before aggregation.", - "is_request_body_field": true, - "entity": { - "is_string": true - } - }, { "name": "full_name", "description": "The full three-part name (catalog, schema, name) of the feature. This is the\nfeature's resource identifier; the catalog_name, schema_name, and name fields\nbelow are OUTPUT_ONLY decomposed views of this value.", @@ -119529,17 +120547,6 @@ "is_object": true } }, - { - "name": "inputs", - "description": "Deprecated: Use AggregationFunction.inputs instead. Kept for backwards compatibility.\nThe input columns from which the feature is computed.", - "is_request_body_field": true, - "entity": { - "pascal_name": "List", - "array_value": { - "is_string": true - } - } - }, { "name": "lineage_context", "description": "Lineage context information for this feature.\nWARNING: This field is primarily intended for internal use by Databricks systems and\nis automatically populated when features are created through Databricks notebooks or jobs.\nUsers should not manually set this field as incorrect values may lead to inaccurate lineage tracking or unexpected behavior.\nThis field will be set by feature-engineering client and should be left unset by SDK and terraform users.", @@ -119578,16 +120585,6 @@ "is_object": true } }, - { - "name": "time_window", - "description": "Deprecated: Use Function.aggregation_function.time_window instead. Kept for backwards compatibility.\nThe time window in which the feature is computed.", - "is_request_body_field": true, - "is_optional_object": true, - "entity": { - "pascal_name": "TimeWindow", - "is_object": true - } - }, { "name": "timeseries_column", "description": "Column recording time, used for point-in-time joins, backfills, and aggregations.", @@ -120199,14 +121196,6 @@ ] } }, - { - "name": "cron_schedule", - "description": "The quartz cron expression that defines the schedule of the materialization pipeline. The schedule is evaluated in the UTC timezone.\nHidden from GraphQL: superseded by the `trigger` oneof (cron_schedule_trigger), so not exposed to Catalog Explorer.", - "is_request_body_field": true, - "entity": { - "is_string": true - } - }, { "name": "cron_schedule_trigger", "description": "A cron-based schedule trigger for the materialization pipeline.", @@ -122304,14 +123293,6 @@ } } }, - { - "name": "filter_condition", - "description": "Deprecated: Use DeltaTableSource.filter_condition or KafkaSource.filter_condition instead. Kept for backwards compatibility.\nThe filter condition applied to the source data before aggregation.", - "is_request_body_field": true, - "entity": { - "is_string": true - } - }, { "name": "full_name", "description": "The full three-part name (catalog, schema, name) of the feature. This is the\nfeature's resource identifier; the catalog_name, schema_name, and name fields\nbelow are OUTPUT_ONLY decomposed views of this value.", @@ -122331,17 +123312,6 @@ "is_object": true } }, - { - "name": "inputs", - "description": "Deprecated: Use AggregationFunction.inputs instead. Kept for backwards compatibility.\nThe input columns from which the feature is computed.", - "is_request_body_field": true, - "entity": { - "pascal_name": "List", - "array_value": { - "is_string": true - } - } - }, { "name": "lineage_context", "description": "Lineage context information for this feature.\nWARNING: This field is primarily intended for internal use by Databricks systems and\nis automatically populated when features are created through Databricks notebooks or jobs.\nUsers should not manually set this field as incorrect values may lead to inaccurate lineage tracking or unexpected behavior.\nThis field will be set by feature-engineering client and should be left unset by SDK and terraform users.", @@ -122380,16 +123350,6 @@ "is_object": true } }, - { - "name": "time_window", - "description": "Deprecated: Use Function.aggregation_function.time_window instead. Kept for backwards compatibility.\nThe time window in which the feature is computed.", - "is_request_body_field": true, - "is_optional_object": true, - "entity": { - "pascal_name": "TimeWindow", - "is_object": true - } - }, { "name": "timeseries_column", "description": "Column recording time, used for point-in-time joins, backfills, and aggregations.", @@ -123134,14 +124094,6 @@ "is_string": true } }, - { - "name": "cron_schedule", - "description": "The quartz cron expression that defines the schedule of the materialization pipeline. The schedule is evaluated in the UTC timezone.\nHidden from GraphQL: superseded by the `trigger` oneof (cron_schedule_trigger), so not exposed to Catalog Explorer.", - "is_request_body_field": true, - "entity": { - "is_string": true - } - }, { "name": "cron_schedule_trigger", "description": "A cron-based schedule trigger for the materialization pipeline.", @@ -127768,10 +128720,8 @@ "is_crud_read": true, "is_response_byte_stream": true, "has_required_positional_arguments": true, - "launch_stage": "PUBLIC_BETA", - "cli_launch_stage_label": "*Beta*", - "cli_launch_stage_banner": "This command is in Beta and may change without notice.", - "cli_launch_stage_display": "Beta", + "launch_stage": "GA", + "cli_launch_stage_display": "GA", "request": { "pascal_name": "DownloadMessageAttachmentVisualizationRequest", "is_object": true, @@ -127985,29 +128935,162 @@ "entity": { "is_string": true } - }, - { - "name": "attachment_id", - "description": "Attachment ID", - "required": true, - "is_path": true, - "entity": { - "is_string": true - } + }, + { + "name": "attachment_id", + "description": "Attachment ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + { + "name": "ExecuteMessageQuery", + "description": "DEPRECATED: Use [Execute Message Attachment Query](:method:genie/executemessageattachmentquery) instead.", + "summary": "[Deprecated] Execute SQL query in a conversation message.", + "path": "/api/2.0/genie/spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}/execute-query", + "is_hidden_cli": true, + "has_required_positional_arguments": true, + "launch_stage": "PRIVATE_PREVIEW", + "cli_launch_stage_display": "Private Preview", + "request": { + "pascal_name": "GenieExecuteMessageQueryRequest", + "is_object": true, + "required_fields": [ + { + "name": "space_id", + "description": "Genie space ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "conversation_id", + "description": "Conversation ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "message_id", + "description": "Message ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_in_url_fields": [ + { + "name": "space_id", + "description": "Genie space ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "conversation_id", + "description": "Conversation ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "message_id", + "description": "Message ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + "response": { + "pascal_name": "GenieGetMessageQueryResultResponse", + "is_object": true + }, + "all_fields": [ + { + "name": "conversation_id", + "description": "Conversation ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "message_id", + "description": "Message ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "space_id", + "description": "Genie space ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_positional_arguments": [ + { + "name": "space_id", + "description": "Genie space ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "conversation_id", + "description": "Conversation ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "message_id", + "description": "Message ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } } ] }, { - "name": "ExecuteMessageQuery", - "description": "DEPRECATED: Use [Execute Message Attachment Query](:method:genie/executemessageattachmentquery) instead.", - "summary": "[Deprecated] Execute SQL query in a conversation message.", - "path": "/api/2.0/genie/spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}/execute-query", - "is_hidden_cli": true, + "name": "GenerateDownloadFullQueryResult", + "description": "Initiates a new SQL execution and returns a `download_id` and `download_id_signature` that you can use to track the progress of the download.\nThe query result is stored in an external link and can be retrieved using the [Get Download Full Query Result](:method:genie/getdownloadfullqueryresult) API.\nBoth `download_id` and `download_id_signature` must be provided when calling the Get endpoint.\n\n----\n\n### **Warning: Databricks strongly recommends that you protect the URLs that are returned by the `EXTERNAL_LINKS` disposition.**\n\nWhen you use the `EXTERNAL_LINKS` disposition, a\nshort-lived, URL is generated, which can be\nused to download the results directly\nfrom . As a\nshort-lived is\nembedded in this URL, you should protect\nthe URL.\n\nBecause URLs are already generated with\nembedded temporary s,\nyou must not set an `Authorization` header in the download requests.\n\nSee [Execute Statement](:method:statementexecution/executestatement) for more details.\n\n----", + "summary": "Generate full query result download.", + "path": "/api/2.0/genie/spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}/attachments/{attachment_id}/downloads", "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "GA", + "cli_launch_stage_display": "GA", "request": { - "pascal_name": "GenieExecuteMessageQueryRequest", + "pascal_name": "GenieGenerateDownloadFullQueryResultRequest", "is_object": true, "required_fields": [ { @@ -128036,6 +129119,15 @@ "entity": { "is_string": true } + }, + { + "name": "attachment_id", + "description": "Attachment ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } } ], "required_in_url_fields": [ @@ -128065,14 +129157,32 @@ "entity": { "is_string": true } + }, + { + "name": "attachment_id", + "description": "Attachment ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } } ] }, "response": { - "pascal_name": "GenieGetMessageQueryResultResponse", + "pascal_name": "GenieGenerateDownloadFullQueryResultResponse", "is_object": true }, "all_fields": [ + { + "name": "attachment_id", + "description": "Attachment ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, { "name": "conversation_id", "description": "Conversation ID", @@ -128128,24 +129238,33 @@ "entity": { "is_string": true } + }, + { + "name": "attachment_id", + "description": "Attachment ID", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } } ] }, { - "name": "GenerateDownloadFullQueryResult", - "description": "Initiates a new SQL execution and returns a `download_id` and `download_id_signature` that you can use to track the progress of the download.\nThe query result is stored in an external link and can be retrieved using the [Get Download Full Query Result](:method:genie/getdownloadfullqueryresult) API.\nBoth `download_id` and `download_id_signature` must be provided when calling the Get endpoint.\n\n----\n\n### **Warning: Databricks strongly recommends that you protect the URLs that are returned by the `EXTERNAL_LINKS` disposition.**\n\nWhen you use the `EXTERNAL_LINKS` disposition, a\nshort-lived, URL is generated, which can be\nused to download the results directly\nfrom . As a\nshort-lived is\nembedded in this URL, you should protect\nthe URL.\n\nBecause URLs are already generated with\nembedded temporary s,\nyou must not set an `Authorization` header in the download requests.\n\nSee [Execute Statement](:method:statementexecution/executestatement) for more details.\n\n----", - "summary": "Generate full query result download.", - "path": "/api/2.0/genie/spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}/attachments/{attachment_id}/downloads", + "name": "GenieCancelResponse", + "description": "Cancels an in-flight agent-mode response. `response_id` is the id returned in the\n`response.created` event from the agent-mode responses endpoint. The response stops at\nthe next agent boundary and its terminal state is returned.", + "summary": "Cancel Genie agent response.", + "path": "/api/2.0/genie/agents/{agent_id}/conversations/{conversation_id}/responses/{response_id}/cancel", "has_required_positional_arguments": true, "launch_stage": "GA", "cli_launch_stage_display": "GA", "request": { - "pascal_name": "GenieGenerateDownloadFullQueryResultRequest", + "pascal_name": "GenieCancelResponseRequest", "is_object": true, "required_fields": [ { - "name": "space_id", - "description": "Genie space ID", + "name": "agent_id", + "description": "The ID of the Genie agent (synonymous with the Genie space ID).", "required": true, "is_path": true, "entity": { @@ -128154,7 +129273,7 @@ }, { "name": "conversation_id", - "description": "Conversation ID", + "description": "The ID of the conversation containing the response.", "required": true, "is_path": true, "entity": { @@ -128162,8 +129281,19 @@ } }, { - "name": "message_id", - "description": "Message ID", + "name": "response_id", + "description": "The ID of the response to cancel (the id from the `response.created` event).", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_in_url_fields": [ + { + "name": "agent_id", + "description": "The ID of the Genie agent (synonymous with the Genie space ID).", "required": true, "is_path": true, "entity": { @@ -128171,21 +129301,35 @@ } }, { - "name": "attachment_id", - "description": "Attachment ID", + "name": "conversation_id", + "description": "The ID of the conversation containing the response.", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "response_id", + "description": "The ID of the response to cancel (the id from the `response.created` event).", "required": true, "is_path": true, "entity": { "is_string": true } } - ], - "required_in_url_fields": [ + ] + }, + "response": { + "pascal_name": "GenieMessage", + "is_object": true, + "has_required_request_body_fields": true, + "required_fields": [ { "name": "space_id", "description": "Genie space ID", "required": true, - "is_path": true, + "is_request_body_field": true, "entity": { "is_string": true } @@ -128194,7 +129338,16 @@ "name": "conversation_id", "description": "Conversation ID", "required": true, - "is_path": true, + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "content", + "description": "User message content", + "required": true, + "is_request_body_field": true, "entity": { "is_string": true } @@ -128203,30 +129356,55 @@ "name": "message_id", "description": "Message ID", "required": true, - "is_path": true, + "is_request_body_field": true, + "entity": { + "is_string": true + } + } + ], + "required_request_body_fields": [ + { + "name": "space_id", + "description": "Genie space ID", + "required": true, + "is_request_body_field": true, "entity": { "is_string": true } }, { - "name": "attachment_id", - "description": "Attachment ID", + "name": "conversation_id", + "description": "Conversation ID", "required": true, - "is_path": true, + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "content", + "description": "User message content", + "required": true, + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "message_id", + "description": "Message ID", + "required": true, + "is_request_body_field": true, "entity": { "is_string": true } } ] }, - "response": { - "pascal_name": "GenieGenerateDownloadFullQueryResultResponse", - "is_object": true - }, "all_fields": [ { - "name": "attachment_id", - "description": "Attachment ID", + "name": "agent_id", + "description": "The ID of the Genie agent (synonymous with the Genie space ID).", "required": true, "is_path": true, "entity": { @@ -128235,7 +129413,7 @@ }, { "name": "conversation_id", - "description": "Conversation ID", + "description": "The ID of the conversation containing the response.", "required": true, "is_path": true, "entity": { @@ -128243,17 +129421,8 @@ } }, { - "name": "message_id", - "description": "Message ID", - "required": true, - "is_path": true, - "entity": { - "is_string": true - } - }, - { - "name": "space_id", - "description": "Genie space ID", + "name": "response_id", + "description": "The ID of the response to cancel (the id from the `response.created` event).", "required": true, "is_path": true, "entity": { @@ -128263,8 +129432,8 @@ ], "required_positional_arguments": [ { - "name": "space_id", - "description": "Genie space ID", + "name": "agent_id", + "description": "The ID of the Genie agent (synonymous with the Genie space ID).", "required": true, "is_path": true, "entity": { @@ -128273,16 +129442,7 @@ }, { "name": "conversation_id", - "description": "Conversation ID", - "required": true, - "is_path": true, - "entity": { - "is_string": true - } - }, - { - "name": "message_id", - "description": "Message ID", + "description": "The ID of the conversation containing the response.", "required": true, "is_path": true, "entity": { @@ -128290,8 +129450,8 @@ } }, { - "name": "attachment_id", - "description": "Attachment ID", + "name": "response_id", + "description": "The ID of the response to cancel (the id from the `response.created` event).", "required": true, "is_path": true, "entity": { @@ -133795,10 +134955,11 @@ "summary": "Create a direct group membership.", "path": "/api/2.0/identity/accounts/{account_id}/groups/{group_id}/direct-members", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "CreateDirectGroupMemberRequest", "is_object": true, @@ -134052,10 +135213,11 @@ "summary": "Create a group in the account.", "path": "/api/2.0/identity/accounts/{account_id}/groups", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "CreateGroupRequest", "is_object": true, @@ -134152,10 +135314,11 @@ "summary": "Create a service principal in the account.", "path": "/api/2.0/identity/accounts/{account_id}/service-principals", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "CreateServicePrincipalRequest", "is_object": true, @@ -134478,10 +135641,11 @@ "summary": "Create a user in the account.", "path": "/api/2.0/identity/accounts/{account_id}/users", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "CreateUserRequest", "is_object": true, @@ -134867,10 +136031,11 @@ "summary": "Create a workspace assignment.", "path": "/api/2.0/identity/accounts/{account_id}/workspaces/{workspace_id}/workspace-assignments", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "CreateWorkspaceAssignmentRequest", "is_object": true, @@ -135157,7 +136322,7 @@ }, { "name": "CreateWorkspaceAssignmentDetail", - "description": "Creates a workspace assignment detail for a principal. Entitlements are granted one at a time\nrather than atomically. If the request fails partway through, the principal stays assigned to\nthe workspace with only some of the requested entitlements. Get the assignment detail\nafterwards to confirm which entitlements were granted.", + "description": "Creates a workspace assignment detail for a principal.", "summary": "Create a workspace assignment detail.", "path": "/api/2.0/identity/accounts/{account_id}/workspaces/{workspace_id}/workspace-assignment-details", "can_use_json": true, @@ -135453,10 +136618,11 @@ "description": "Deletes a group membership (unassigns a principal from a group).", "summary": "Delete a direct group membership.", "path": "/api/2.0/identity/accounts/{account_id}/groups/{group_id}/direct-members/{principal_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "DeleteDirectGroupMemberRequest", "is_object": true, @@ -135550,10 +136716,11 @@ "description": "Deletes a group from the Databricks account by its internal ID.", "summary": "Delete a group in the account.", "path": "/api/2.0/identity/accounts/{account_id}/groups/{group_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "DeleteGroupRequest", "is_object": true, @@ -135611,10 +136778,11 @@ "description": "Deletes a service principal from the Databricks account by its internal ID.", "summary": "Delete a service principal in the account.", "path": "/api/2.0/identity/accounts/{account_id}/service-principals/{service_principal_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "DeleteServicePrincipalRequest", "is_object": true, @@ -135672,10 +136840,11 @@ "description": "Deletes a user from the Databricks account by its internal ID.", "summary": "Delete a user in the account.", "path": "/api/2.0/identity/accounts/{account_id}/users/{user_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "DeleteUserRequest", "is_object": true, @@ -135733,10 +136902,11 @@ "description": "Deletes a workspace assignment for a principal, revoking all of its entitlements.\nEntitlements are revoked one at a time rather than atomically. If the request fails partway\nthrough, the principal stays assigned with some of its original entitlements. Retrying is safe.", "summary": "Delete a workspace assignment.", "path": "/api/2.0/identity/accounts/{account_id}/workspaces/{workspace_id}/workspace-assignments/{principal_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "DeleteWorkspaceAssignmentRequest", "is_object": true, @@ -135927,10 +137097,11 @@ "description": "Gets a provisioned direct member of a group.", "summary": "Get a direct group member.", "path": "/api/2.0/identity/accounts/{account_id}/groups/{group_id}/direct-members/{principal_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "GetDirectGroupMemberRequest", "is_object": true, @@ -136043,15 +137214,205 @@ } ] }, + { + "name": "GetExternalGroup", + "description": "Retrieves an external group with the given external ID from the customer's\nIdP. If the group does not exist, it will be created in the account. If the\ncustomer is not onboarded onto Automatic Identity Management (AIM), this will\nreturn an error.", + "summary": "Get an external group in the account.", + "path": "/api/2.0/identity/{name=accounts/*/external-groups/*}", + "has_required_positional_arguments": true, + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", + "request": { + "pascal_name": "GetExternalGroupRequest", + "is_object": true, + "required_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external group.\nFormat: accounts/{account_id}/external-groups/{external_group_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_in_url_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external group.\nFormat: accounts/{account_id}/external-groups/{external_group_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + "response": { + "pascal_name": "ExternalGroup", + "is_object": true + }, + "all_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external group.\nFormat: accounts/{account_id}/external-groups/{external_group_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_positional_arguments": [ + { + "name": "name", + "description": "Required. The resource name of the external group.\nFormat: accounts/{account_id}/external-groups/{external_group_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + { + "name": "GetExternalServicePrincipal", + "description": "Retrieves an external service principal with the given external ID from the\ncustomer's IdP. If the service principal does not exist, it will be created.\nIf the customer is not onboarded onto Automatic Identity Management (AIM),\nthis will return an error.", + "summary": "Get an external service principal in the account.", + "path": "/api/2.0/identity/{name=accounts/*/external-service-principals/*}", + "has_required_positional_arguments": true, + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", + "request": { + "pascal_name": "GetExternalServicePrincipalRequest", + "is_object": true, + "required_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external service principal.\nFormat: accounts/{account_id}/external-service-principals/{external_service_principal_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_in_url_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external service principal.\nFormat: accounts/{account_id}/external-service-principals/{external_service_principal_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + "response": { + "pascal_name": "ExternalServicePrincipal", + "is_object": true + }, + "all_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external service principal.\nFormat: accounts/{account_id}/external-service-principals/{external_service_principal_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_positional_arguments": [ + { + "name": "name", + "description": "Required. The resource name of the external service principal.\nFormat: accounts/{account_id}/external-service-principals/{external_service_principal_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + { + "name": "GetExternalUser", + "description": "Retrieves an external user with the given external ID from the customer's\nIdP. If the user does not exist, it will be created. If the customer is not\nonboarded onto Automatic Identity Management (AIM), this will return an error.", + "summary": "Get an external user in the account.", + "path": "/api/2.0/identity/{name=accounts/*/external-users/*}", + "has_required_positional_arguments": true, + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", + "request": { + "pascal_name": "GetExternalUserRequest", + "is_object": true, + "required_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external user.\nFormat: accounts/{account_id}/external-users/{external_user_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_in_url_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external user.\nFormat: accounts/{account_id}/external-users/{external_user_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + "response": { + "pascal_name": "ExternalUser", + "is_object": true + }, + "all_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external user.\nFormat: accounts/{account_id}/external-users/{external_user_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_positional_arguments": [ + { + "name": "name", + "description": "Required. The resource name of the external user.\nFormat: accounts/{account_id}/external-users/{external_user_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, { "name": "GetGroup", "description": "Fetches a group from the Databricks account by its internal ID.", "summary": "Get a group in the account.", "path": "/api/2.0/identity/accounts/{account_id}/groups/{group_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "GetGroupRequest", "is_object": true, @@ -136110,10 +137471,11 @@ "description": "Fetches a service principal from the Databricks account by its internal ID.", "summary": "Get a service principal in the account.", "path": "/api/2.0/identity/accounts/{account_id}/service-principals/{service_principal_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "GetServicePrincipalRequest", "is_object": true, @@ -136229,10 +137591,11 @@ "description": "Fetches a user from the Databricks account by its internal ID.", "summary": "Get a user in the account.", "path": "/api/2.0/identity/accounts/{account_id}/users/{user_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "GetUserRequest", "is_object": true, @@ -136481,10 +137844,11 @@ "description": "Returns the assignment for a principal in a workspace.", "summary": "Get a workspace assignment for a principal.", "path": "/api/2.0/identity/accounts/{account_id}/workspaces/{workspace_id}/workspace-assignments/{principal_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "GetWorkspaceAssignmentRequest", "is_object": true, @@ -136723,10 +138087,11 @@ "description": "Lists provisioned direct members of a group with their membership source (internal or from identity provider).", "summary": "List direct group members.", "path": "/api/2.0/identity/accounts/{account_id}/groups/{group_id}/direct-members", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "ListDirectGroupMembersRequest", "is_object": true, @@ -136769,7 +138134,7 @@ }, { "name": "page_size", - "description": "The maximum number of members to return. The service may return fewer than this value.\nIf not provided, defaults to 1000 (also the maximum allowed).", + "description": "The maximum number of members to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", "is_query": true, "entity": { "is_int": true @@ -136813,10 +138178,11 @@ "description": "Lists the groups in the Databricks account, returning one page per call. Supports filtering by\ngroup name or external ID.", "summary": "List groups in the account.", "path": "/api/2.0/identity/accounts/{account_id}/groups", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "ListGroupsRequest", "is_object": true @@ -136836,7 +138202,7 @@ }, { "name": "page_size", - "description": "The maximum number of groups to return. The service may return fewer than this value.", + "description": "The maximum number of groups to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", "is_query": true, "entity": { "is_int": true @@ -136869,10 +138235,11 @@ "description": "Lists the service principals in the Databricks account, returning one page per call. Supports\nfiltering by application ID or external ID.", "summary": "List service principals in the account.", "path": "/api/2.0/identity/accounts/{account_id}/service-principals", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "ListServicePrincipalsRequest", "is_object": true @@ -136892,7 +138259,7 @@ }, { "name": "page_size", - "description": "The maximum number of service principals to return. The service may return fewer than this value.", + "description": "The maximum number of service principals to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", "is_query": true, "entity": { "is_int": true @@ -136925,10 +138292,11 @@ "description": "Lists all transitive parent groups of a principal.", "summary": "List all transitive parent groups of a principal.", "path": "/api/2.0/identity/accounts/{account_id}/principals/{principal_id}/transitive-parent-groups", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "ListTransitiveParentGroupsRequest", "is_object": true, @@ -136962,7 +138330,7 @@ "all_fields": [ { "name": "page_size", - "description": "The maximum number of parent groups to return. The service may return fewer than this value.\nIf not provided, defaults to 1000 (also the maximum allowed).", + "description": "The maximum number of parent groups to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", "is_query": true, "entity": { "is_int": true @@ -137003,10 +138371,11 @@ "description": "Lists the users in the Databricks account, returning one page per call. Supports filtering by\nusername or external ID.", "summary": "List users in the account.", "path": "/api/2.0/identity/accounts/{account_id}/users", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "ListUsersRequest", "is_object": true @@ -137026,7 +138395,7 @@ }, { "name": "page_size", - "description": "The maximum number of users to return. The service may return fewer than this value.", + "description": "The maximum number of users to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", "is_query": true, "entity": { "is_int": true @@ -137096,7 +138465,7 @@ "all_fields": [ { "name": "page_size", - "description": "The maximum number of workspace assignment details to return. The service may return fewer than this value.", + "description": "The maximum number of workspace assignment details to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", "is_query": true, "entity": { "is_int": true @@ -137149,10 +138518,11 @@ "description": "Lists workspace assignments for a workspace. The response omits the per-principal\nentitlement fields (`entitlements` and `effective_entitlements`). To read the entitlements for\na single principal, get that principal's assignment.", "summary": "List workspace assignments for a workspace.", "path": "/api/2.0/identity/accounts/{account_id}/workspaces/{workspace_id}/workspace-assignments", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "ListWorkspaceAssignmentsRequest", "is_object": true, @@ -137186,7 +138556,7 @@ "all_fields": [ { "name": "page_size", - "description": "The maximum number of workspace assignments to return. The service may return fewer than this value.", + "description": "The maximum number of workspace assignments to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", "is_query": true, "entity": { "is_int": true @@ -137435,10 +138805,11 @@ "summary": "Update a group in the account.", "path": "/api/2.0/identity/accounts/{account_id}/groups/{group_id}", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "UpdateGroupRequest", "is_object": true, @@ -137611,10 +138982,11 @@ "summary": "Update a service principal in the account.", "path": "/api/2.0/identity/accounts/{account_id}/service-principals/{service_principal_id}", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "UpdateServicePrincipalRequest", "is_object": true, @@ -138011,10 +139383,11 @@ "summary": "Update a user in the account.", "path": "/api/2.0/identity/accounts/{account_id}/users/{user_id}", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "UpdateUserRequest", "is_object": true, @@ -138474,10 +139847,11 @@ "summary": "Update a workspace assignment.", "path": "/api/2.0/identity/accounts/{account_id}/workspaces/{workspace_id}/workspace-assignments/{principal_id}", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "UpdateWorkspaceAssignmentRequest", "is_object": true, @@ -141766,7 +143140,7 @@ }, { "name": "continuous", - "description": "An optional continuous property for this job. The continuous property will ensure that there is always one run executing. Only one of `schedule` and `continuous` can be used.", + "description": "An optional continuous property for this job. The continuous property will ensure that there is always one run executing. Only one of `schedule` and `continuous` can be used.\n\nPipelines started by a continuous job also run continuously, regardless of their own pipeline mode setting.", "is_request_body_field": true, "is_optional_object": true, "entity": { @@ -147004,7 +148378,7 @@ "methods": [ { "name": "Create", - "description": "Create a draft dashboard.", + "description": "Create a draft dashboard.\n\nRequires the Databricks SQL access entitlement.", "summary": "Create dashboard.", "path": "/api/2.0/lakeview/dashboards", "can_use_json": true, @@ -148034,7 +149408,7 @@ }, { "name": "Get", - "description": "Get a draft dashboard.", + "description": "Get a draft dashboard.\n\nRequires the Databricks SQL access entitlement.", "summary": "Get dashboard.", "path": "/api/2.0/lakeview/dashboards/{dashboard_id}", "is_crud_read": true, @@ -148096,7 +149470,7 @@ }, { "name": "GetPublished", - "description": "Get the current published dashboard.", + "description": "Get the current published dashboard.\n\nRequires one of the following entitlements: Workspace access,\nDatabricks SQL access, or Consumer access.", "summary": "Get published dashboard.", "path": "/api/2.0/lakeview/dashboards/{dashboard_id}/published", "is_crud_read": true, @@ -148440,7 +149814,7 @@ }, { "name": "List", - "description": "List dashboards.", + "description": "List dashboards.\n\nRequires the Databricks SQL access entitlement.", "summary": "List dashboards.", "path": "/api/2.0/lakeview/dashboards", "has_required_positional_arguments": true, @@ -148810,7 +150184,7 @@ }, { "name": "Publish", - "description": "Publish the current draft dashboard.", + "description": "Publish the current draft dashboard.\n\nRequires the Databricks SQL access entitlement.", "summary": "Publish dashboard.", "path": "/api/2.0/lakeview/dashboards/{dashboard_id}/published", "can_use_json": true, @@ -148889,7 +150263,7 @@ }, { "name": "Revert", - "description": "Revert a dashboard's definition in draft mode to the last published version.", + "description": "Revert a dashboard's definition in draft mode to the last published version.\n\nRequires the Databricks SQL access entitlement.", "summary": "Revert dashboard.", "path": "/api/2.0/lakeview/dashboards/{dashboard_id}/revert", "can_use_json": true, @@ -148960,7 +150334,7 @@ }, { "name": "Trash", - "description": "Trash a dashboard.", + "description": "Trash a dashboard.\n\nRequires the Databricks SQL access entitlement.", "summary": "Trash dashboard.", "path": "/api/2.0/lakeview/dashboards/{dashboard_id}", "has_required_positional_arguments": true, @@ -149022,7 +150396,7 @@ }, { "name": "Unpublish", - "description": "Unpublish the dashboard.", + "description": "Unpublish the dashboard.\n\nRequires the Databricks SQL access entitlement.", "summary": "Unpublish dashboard.", "path": "/api/2.0/lakeview/dashboards/{dashboard_id}/published", "has_required_positional_arguments": true, @@ -149084,7 +150458,7 @@ }, { "name": "Update", - "description": "Update a draft dashboard.", + "description": "Update a draft dashboard.\n\nRequires the Databricks SQL access entitlement.", "summary": "Update dashboard.", "path": "/api/2.0/lakeview/dashboards/{dashboard_id}", "can_use_json": true, @@ -149643,7 +151017,7 @@ "methods": [ { "name": "GetPublishedDashboardTokenInfo", - "description": "Get a required authorization details and scopes of a published dashboard to mint an OAuth token.", + "description": "Get a required authorization details and scopes of a published dashboard to mint an OAuth token.\n\nRequires one of the following entitlements: Workspace access,\nDatabricks SQL access, or Consumer access.", "summary": "Read information of a published dashboard to mint an OAuth token.", "path": "/api/2.0/lakeview/dashboards/{dashboard_id}/published/tokeninfo", "is_crud_read": true, @@ -161410,7 +162784,7 @@ }, { "name": "continuous", - "description": "Whether the pipeline is continuous or triggered. This replaces `trigger`.", + "description": "Whether the pipeline is continuous or triggered. This replaces `trigger`.\n\nDeprecated: wrap the pipeline in a continuous job instead, which also lets you take advantage\nof job-level settings such as performance mode. When the pipeline is started by a continuous\njob, the job's setting takes precedence and this field is ignored.", "is_request_body_field": true, "entity": { "is_bool": true @@ -161732,7 +163106,7 @@ }, { "name": "continuous", - "description": "Whether the pipeline is continuous or triggered. This replaces `trigger`.", + "description": "Whether the pipeline is continuous or triggered. This replaces `trigger`.\n\nDeprecated: wrap the pipeline in a continuous job instead, which also lets you take advantage\nof job-level settings such as performance mode. When the pipeline is started by a continuous\njob, the job's setting takes precedence and this field is ignored.", "is_request_body_field": true, "entity": { "is_bool": true @@ -163010,7 +164384,7 @@ }, { "name": "continuous", - "description": "Whether the pipeline is continuous or triggered. This replaces `trigger`.", + "description": "Whether the pipeline is continuous or triggered. This replaces `trigger`.\n\nDeprecated: wrap the pipeline in a continuous job instead, which also lets you take advantage\nof job-level settings such as performance mode. When the pipeline is started by a continuous\njob, the job's setting takes precedence and this field is ignored.", "is_request_body_field": true, "entity": { "is_bool": true @@ -163456,9 +164830,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -163552,9 +164938,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -163654,9 +165052,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -163750,9 +165160,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -163857,9 +165279,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -163953,9 +165387,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -164088,262 +165534,298 @@ "content": "FUNCTION" }, { - "content": "METASTORE" - }, - { - "content": "PIPELINE" - }, - { - "content": "PROVIDER" - }, - { - "content": "RECIPIENT" - }, - { - "content": "SCHEMA" - }, - { - "content": "SHARE" - }, - { - "content": "STAGING_TABLE" - }, - { - "content": "STORAGE_CREDENTIAL" - }, - { - "content": "TABLE" - }, - { - "content": "VOLUME" - } - ] - } - }, - { - "name": "grant", - "description": "Options for grant policies. Valid only if `policy_type` is `POLICY_TYPE_GRANT`.\nRequired on create and optional on update. When specified on update,\nthe new options will replace the existing options as a whole.", - "is_request_body_field": true, - "is_optional_object": true, - "entity": { - "pascal_name": "GrantOptions", - "is_object": true - } - }, - { - "name": "id", - "description": "Unique identifier of the policy. This field is output only and is generated by the system.", - "is_computed": true, - "is_output_only": true, - "is_request_body_field": true, - "entity": { - "is_string": true - } - }, - { - "name": "match_columns", - "description": "Optional list of condition expressions used to match table columns.\nOnly valid when `for_securable_type` is `TABLE`.\nWhen specified, the policy only applies to tables whose columns satisfy all match conditions.", - "is_request_body_field": true, - "entity": { - "pascal_name": "MatchColumnList", - "array_value": { - "pascal_name": "MatchColumn", - "is_object": true - } - } - }, - { - "name": "name", - "description": "Name of the policy. Required on create and optional on update.\nTo rename the policy, set `name` to a different value on update.", - "is_request_body_field": true, - "entity": { - "is_string": true - } - }, - { - "name": "on_securable_fullname", - "description": "Full name of the securable on which the policy is defined.\nRequired on create.", - "is_request_body_field": true, - "entity": { - "is_string": true - } - }, - { - "name": "on_securable_type", - "description": "Type of the securable on which the policy is defined.\nOnly `CATALOG`, `SCHEMA` and `TABLE` are supported at this moment.\nRequired on create.", - "is_request_body_field": true, - "entity": { - "pascal_name": "SecurableType", - "enum": [ - { - "content": "CATALOG" - }, - { - "content": "CLEAN_ROOM" - }, - { - "content": "CONNECTION" - }, - { - "content": "CREDENTIAL" - }, - { - "content": "EXTERNAL_LOCATION" - }, - { - "content": "EXTERNAL_METADATA" - }, - { - "content": "FUNCTION" + "content": "MCP_SERVICE" + }, + { + "content": "METASTORE" + }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, + { + "content": "PIPELINE" + }, + { + "content": "PROVIDER" + }, + { + "content": "RECIPIENT" + }, + { + "content": "SCHEMA" + }, + { + "content": "SHARE" + }, + { + "content": "STAGING_TABLE" + }, + { + "content": "STORAGE_CREDENTIAL" + }, + { + "content": "TABLE" + }, + { + "content": "VOLUME" + } + ] + } + }, + { + "name": "grant", + "description": "Options for grant policies. Valid only if `policy_type` is `POLICY_TYPE_GRANT`.\nRequired on create and optional on update. When specified on update,\nthe new options will replace the existing options as a whole.", + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "pascal_name": "GrantOptions", + "is_object": true + } + }, + { + "name": "id", + "description": "Unique identifier of the policy. This field is output only and is generated by the system.", + "is_computed": true, + "is_output_only": true, + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "match_columns", + "description": "Optional list of condition expressions used to match table columns.\nOnly valid when `for_securable_type` is `TABLE`.\nWhen specified, the policy only applies to tables whose columns satisfy all match conditions.", + "is_request_body_field": true, + "entity": { + "pascal_name": "MatchColumnList", + "array_value": { + "pascal_name": "MatchColumn", + "is_object": true + } + } + }, + { + "name": "name", + "description": "Name of the policy. Required on create and optional on update.\nTo rename the policy, set `name` to a different value on update.", + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "on_securable_fullname", + "description": "Full name of the securable on which the policy is defined.\nRequired on create.", + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "on_securable_type", + "description": "Type of the securable on which the policy is defined.\nOnly `CATALOG`, `SCHEMA` and `TABLE` are supported at this moment.\nRequired on create.", + "is_request_body_field": true, + "entity": { + "pascal_name": "SecurableType", + "enum": [ + { + "content": "CATALOG" + }, + { + "content": "CLEAN_ROOM" + }, + { + "content": "CONNECTION" + }, + { + "content": "CREDENTIAL" + }, + { + "content": "EXTERNAL_LOCATION" + }, + { + "content": "EXTERNAL_METADATA" + }, + { + "content": "FUNCTION" + }, + { + "content": "MCP_SERVICE" + }, + { + "content": "METASTORE" + }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, + { + "content": "PIPELINE" + }, + { + "content": "PROVIDER" + }, + { + "content": "RECIPIENT" + }, + { + "content": "SCHEMA" + }, + { + "content": "SHARE" + }, + { + "content": "STAGING_TABLE" + }, + { + "content": "STORAGE_CREDENTIAL" + }, + { + "content": "TABLE" + }, + { + "content": "VOLUME" + } + ] + } + }, + { + "name": "policy_type", + "description": "Type of the policy. Required on create.", + "required": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "PolicyType", + "enum": [ + { + "content": "POLICY_TYPE_COLUMN_MASK" + }, + { + "content": "POLICY_TYPE_GRANT" + }, + { + "content": "POLICY_TYPE_ROW_FILTER" + } + ] + } + }, + { + "name": "row_filter", + "description": "Options for row filter policies. Valid only if `policy_type` is `POLICY_TYPE_ROW_FILTER`.\nRequired on create and optional on update. When specified on update,\nthe new options will replace the existing options as a whole.", + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "pascal_name": "RowFilterOptions", + "is_object": true + } + }, + { + "name": "to_principals", + "description": "List of user or group names that the policy applies to.\nRequired on create and optional on update.", + "required": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "List", + "array_value": { + "is_string": true + } + } + }, + { + "name": "updated_at", + "description": "Time at which the policy was last modified, in epoch milliseconds. Output only.", + "is_computed": true, + "is_output_only": true, + "is_request_body_field": true, + "entity": { + "is_int64": true + } + }, + { + "name": "updated_by", + "description": "Username of the user who last modified the policy. Output only.", + "is_computed": true, + "is_output_only": true, + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "when_condition", + "description": "Optional condition when the policy should take effect.", + "is_request_body_field": true, + "entity": { + "is_string": true + } + } + ], + "required_positional_arguments": [ + { + "name": "to_principals", + "description": "List of user or group names that the policy applies to.\nRequired on create and optional on update.", + "required": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "List", + "array_value": { + "is_string": true + } + } + }, + { + "name": "for_securable_type", + "description": "Type of securables that the policy should take effect on.\nRequired on create and optional on update.", + "required": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "SecurableType", + "enum": [ + { + "content": "CATALOG" + }, + { + "content": "CLEAN_ROOM" + }, + { + "content": "CONNECTION" + }, + { + "content": "CREDENTIAL" + }, + { + "content": "EXTERNAL_LOCATION" + }, + { + "content": "EXTERNAL_METADATA" + }, + { + "content": "FUNCTION" + }, + { + "content": "MCP_SERVICE" }, { "content": "METASTORE" }, { - "content": "PIPELINE" - }, - { - "content": "PROVIDER" - }, - { - "content": "RECIPIENT" - }, - { - "content": "SCHEMA" - }, - { - "content": "SHARE" - }, - { - "content": "STAGING_TABLE" - }, - { - "content": "STORAGE_CREDENTIAL" + "content": "MODEL" }, { - "content": "TABLE" - }, - { - "content": "VOLUME" - } - ] - } - }, - { - "name": "policy_type", - "description": "Type of the policy. Required on create.", - "required": true, - "is_request_body_field": true, - "entity": { - "pascal_name": "PolicyType", - "enum": [ - { - "content": "POLICY_TYPE_COLUMN_MASK" + "content": "MODEL_PROVIDER_SERVICE" }, { - "content": "POLICY_TYPE_GRANT" - }, - { - "content": "POLICY_TYPE_ROW_FILTER" - } - ] - } - }, - { - "name": "row_filter", - "description": "Options for row filter policies. Valid only if `policy_type` is `POLICY_TYPE_ROW_FILTER`.\nRequired on create and optional on update. When specified on update,\nthe new options will replace the existing options as a whole.", - "is_request_body_field": true, - "is_optional_object": true, - "entity": { - "pascal_name": "RowFilterOptions", - "is_object": true - } - }, - { - "name": "to_principals", - "description": "List of user or group names that the policy applies to.\nRequired on create and optional on update.", - "required": true, - "is_request_body_field": true, - "entity": { - "pascal_name": "List", - "array_value": { - "is_string": true - } - } - }, - { - "name": "updated_at", - "description": "Time at which the policy was last modified, in epoch milliseconds. Output only.", - "is_computed": true, - "is_output_only": true, - "is_request_body_field": true, - "entity": { - "is_int64": true - } - }, - { - "name": "updated_by", - "description": "Username of the user who last modified the policy. Output only.", - "is_computed": true, - "is_output_only": true, - "is_request_body_field": true, - "entity": { - "is_string": true - } - }, - { - "name": "when_condition", - "description": "Optional condition when the policy should take effect.", - "is_request_body_field": true, - "entity": { - "is_string": true - } - } - ], - "required_positional_arguments": [ - { - "name": "to_principals", - "description": "List of user or group names that the policy applies to.\nRequired on create and optional on update.", - "required": true, - "is_request_body_field": true, - "entity": { - "pascal_name": "List", - "array_value": { - "is_string": true - } - } - }, - { - "name": "for_securable_type", - "description": "Type of securables that the policy should take effect on.\nRequired on create and optional on update.", - "required": true, - "is_request_body_field": true, - "entity": { - "pascal_name": "SecurableType", - "enum": [ - { - "content": "CATALOG" - }, - { - "content": "CLEAN_ROOM" - }, - { - "content": "CONNECTION" - }, - { - "content": "CREDENTIAL" - }, - { - "content": "EXTERNAL_LOCATION" - }, - { - "content": "EXTERNAL_METADATA" - }, - { - "content": "FUNCTION" - }, - { - "content": "METASTORE" + "content": "MODEL_SERVICE" }, { "content": "PIPELINE" @@ -164647,9 +166129,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -164743,9 +166237,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -165135,9 +166641,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -165231,9 +166749,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -165333,9 +166863,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -165429,9 +166971,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -165563,9 +167117,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -165659,9 +167225,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -165801,9 +167379,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -165910,9 +167500,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -166083,9 +167685,21 @@ { "content": "FUNCTION" }, + { + "content": "MCP_SERVICE" + }, { "content": "METASTORE" }, + { + "content": "MODEL" + }, + { + "content": "MODEL_PROVIDER_SERVICE" + }, + { + "content": "MODEL_SERVICE" + }, { "content": "PIPELINE" }, @@ -168616,6 +170230,216 @@ "response_type": {} } }, + { + "name": "CreateSnapshot", + "description": "Creates a snapshot, an immutable point-in-time copy of a branch's data, within the project.", + "summary": "Create a Snapshot.", + "path": "/api/2.0/postgres/{parent=projects/*}/snapshots", + "can_use_json": true, + "is_crud_create": true, + "is_hidden_cli": true, + "has_required_positional_arguments": true, + "launch_stage": "PRIVATE_PREVIEW", + "cli_launch_stage_display": "Private Preview", + "request": { + "pascal_name": "CreateSnapshotRequest", + "is_object": true, + "has_required_request_body_fields": true, + "required_fields": [ + { + "name": "parent", + "description": "The project in which to create the snapshot.\nFormat: projects/{project_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "snapshot", + "description": "The snapshot to create.", + "required": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "Snapshot", + "is_object": true + } + }, + { + "name": "snapshot_id", + "description": "Client-chosen ID for the snapshot. It becomes the final segment of the\nsnapshot resource name and cannot be changed after creation.", + "required": true, + "is_query": true, + "entity": { + "is_string": true + } + } + ], + "required_in_url_fields": [ + { + "name": "parent", + "description": "The project in which to create the snapshot.\nFormat: projects/{project_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "snapshot_id", + "description": "Client-chosen ID for the snapshot. It becomes the final segment of the\nsnapshot resource name and cannot be changed after creation.", + "required": true, + "is_query": true, + "entity": { + "is_string": true + } + } + ], + "required_request_body_fields": [ + { + "name": "snapshot", + "description": "The snapshot to create.", + "required": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "Snapshot", + "is_object": true + } + } + ] + }, + "request_body_field": { + "name": "snapshot", + "description": "The snapshot to create.", + "required": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "Snapshot", + "is_object": true + } + }, + "response": { + "pascal_name": "Operation", + "is_object": true + }, + "all_fields": [ + { + "name": "parent", + "description": "The project in which to create the snapshot.\nFormat: projects/{project_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "snapshot", + "description": "The snapshot to create.", + "required": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "Snapshot", + "is_object": true + } + }, + { + "name": "snapshot_id", + "description": "Client-chosen ID for the snapshot. It becomes the final segment of the\nsnapshot resource name and cannot be changed after creation.", + "required": true, + "is_query": true, + "entity": { + "is_string": true + } + }, + { + "name": "create_time", + "description": "When the snapshot was created.", + "is_output_only": true, + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "is_timestamp": true + } + }, + { + "name": "name", + "description": "The resource name of the snapshot.\nFormat: projects/{project_id}/snapshots/{snapshot_id}", + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "snapshot_id", + "description": "The user-chosen ID; the final segment of `name`.", + "is_output_only": true, + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "spec", + "description": "Client-provided configuration of the snapshot.", + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "pascal_name": "SnapshotSpec", + "is_object": true + } + }, + { + "name": "status", + "description": "Server-observed state of the snapshot.", + "is_output_only": true, + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "pascal_name": "SnapshotStatus", + "is_object": true + } + }, + { + "name": "uid", + "description": "Unique system-generated ID for the snapshot.", + "is_output_only": true, + "is_request_body_field": true, + "entity": { + "is_string": true + } + } + ], + "required_positional_arguments": [ + { + "name": "parent", + "description": "The project in which to create the snapshot.\nFormat: projects/{project_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "snapshot_id", + "description": "Client-chosen ID for the snapshot. It becomes the final segment of the\nsnapshot resource name and cannot be changed after creation.", + "required": true, + "is_query": true, + "entity": { + "is_string": true + } + } + ], + "long_running_operation": { + "get_operation": { + "kebab_name": "get-operation", + "pascal_name": "GetOperation", + "request": { + "pascal_name": "GetOperationRequest" + } + }, + "response_type": {} + } + }, { "name": "CreateSyncedTable", "description": "Create a Synced Table.", @@ -169096,20 +170920,93 @@ } }, { - "name": "DeleteDatabase", - "description": "Delete a Database.", - "summary": "Delete a Database.", - "path": "/api/2.0/postgres/{name=projects/*/branches/*/databases/*}", + "name": "DeleteDatabase", + "description": "Delete a Database.", + "summary": "Delete a Database.", + "path": "/api/2.0/postgres/{name=projects/*/branches/*/databases/*}", + "has_required_positional_arguments": true, + "launch_stage": "GA", + "cli_launch_stage_display": "GA", + "request": { + "pascal_name": "DeleteDatabaseRequest", + "is_object": true, + "required_fields": [ + { + "name": "name", + "description": "The resource name of the postgres database.\nFormat: projects/{project_id}/branches/{branch_id}/databases/{database_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_in_url_fields": [ + { + "name": "name", + "description": "The resource name of the postgres database.\nFormat: projects/{project_id}/branches/{branch_id}/databases/{database_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + "response": { + "pascal_name": "Operation", + "is_object": true + }, + "all_fields": [ + { + "name": "name", + "description": "The resource name of the postgres database.\nFormat: projects/{project_id}/branches/{branch_id}/databases/{database_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_positional_arguments": [ + { + "name": "name", + "description": "The resource name of the postgres database.\nFormat: projects/{project_id}/branches/{branch_id}/databases/{database_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "long_running_operation": { + "get_operation": { + "kebab_name": "get-operation", + "pascal_name": "GetOperation", + "request": { + "pascal_name": "GetOperationRequest" + } + }, + "response_type": { + "is_empty_response": true + } + } + }, + { + "name": "DeleteEndpoint", + "description": "Deletes the specified compute endpoint.", + "summary": "Delete an Endpoint.", + "path": "/api/2.0/postgres/{name=projects/*/branches/*/endpoints/*}", "has_required_positional_arguments": true, "launch_stage": "GA", "cli_launch_stage_display": "GA", "request": { - "pascal_name": "DeleteDatabaseRequest", + "pascal_name": "DeleteEndpointRequest", "is_object": true, "required_fields": [ { "name": "name", - "description": "The resource name of the postgres database.\nFormat: projects/{project_id}/branches/{branch_id}/databases/{database_id}", + "description": "The full resource path of the endpoint to delete.\nFormat: projects/{project_id}/branches/{branch_id}/endpoints/{endpoint_id}", "required": true, "is_path": true, "entity": { @@ -169120,7 +171017,7 @@ "required_in_url_fields": [ { "name": "name", - "description": "The resource name of the postgres database.\nFormat: projects/{project_id}/branches/{branch_id}/databases/{database_id}", + "description": "The full resource path of the endpoint to delete.\nFormat: projects/{project_id}/branches/{branch_id}/endpoints/{endpoint_id}", "required": true, "is_path": true, "entity": { @@ -169136,7 +171033,7 @@ "all_fields": [ { "name": "name", - "description": "The resource name of the postgres database.\nFormat: projects/{project_id}/branches/{branch_id}/databases/{database_id}", + "description": "The full resource path of the endpoint to delete.\nFormat: projects/{project_id}/branches/{branch_id}/endpoints/{endpoint_id}", "required": true, "is_path": true, "entity": { @@ -169147,7 +171044,7 @@ "required_positional_arguments": [ { "name": "name", - "description": "The resource name of the postgres database.\nFormat: projects/{project_id}/branches/{branch_id}/databases/{database_id}", + "description": "The full resource path of the endpoint to delete.\nFormat: projects/{project_id}/branches/{branch_id}/endpoints/{endpoint_id}", "required": true, "is_path": true, "entity": { @@ -169169,20 +171066,20 @@ } }, { - "name": "DeleteEndpoint", - "description": "Deletes the specified compute endpoint.", - "summary": "Delete an Endpoint.", - "path": "/api/2.0/postgres/{name=projects/*/branches/*/endpoints/*}", + "name": "DeleteProject", + "description": "Deletes the specified database project.", + "summary": "Delete a Project.", + "path": "/api/2.0/postgres/{name=projects/*}", "has_required_positional_arguments": true, "launch_stage": "GA", "cli_launch_stage_display": "GA", "request": { - "pascal_name": "DeleteEndpointRequest", + "pascal_name": "DeleteProjectRequest", "is_object": true, "required_fields": [ { "name": "name", - "description": "The full resource path of the endpoint to delete.\nFormat: projects/{project_id}/branches/{branch_id}/endpoints/{endpoint_id}", + "description": "The full resource path of the project to delete.\nFormat: projects/{project_id}", "required": true, "is_path": true, "entity": { @@ -169193,7 +171090,7 @@ "required_in_url_fields": [ { "name": "name", - "description": "The full resource path of the endpoint to delete.\nFormat: projects/{project_id}/branches/{branch_id}/endpoints/{endpoint_id}", + "description": "The full resource path of the project to delete.\nFormat: projects/{project_id}", "required": true, "is_path": true, "entity": { @@ -169209,18 +171106,26 @@ "all_fields": [ { "name": "name", - "description": "The full resource path of the endpoint to delete.\nFormat: projects/{project_id}/branches/{branch_id}/endpoints/{endpoint_id}", + "description": "The full resource path of the project to delete.\nFormat: projects/{project_id}", "required": true, "is_path": true, "entity": { "is_string": true } + }, + { + "name": "purge", + "description": "If true, permanently deletes the project (hard delete).\nIf false or unset, performs a soft delete.", + "is_query": true, + "entity": { + "is_bool": true + } } ], "required_positional_arguments": [ { "name": "name", - "description": "The full resource path of the endpoint to delete.\nFormat: projects/{project_id}/branches/{branch_id}/endpoints/{endpoint_id}", + "description": "The full resource path of the project to delete.\nFormat: projects/{project_id}", "required": true, "is_path": true, "entity": { @@ -169242,20 +171147,20 @@ } }, { - "name": "DeleteProject", - "description": "Deletes the specified database project.", - "summary": "Delete a Project.", - "path": "/api/2.0/postgres/{name=projects/*}", + "name": "DeleteRole", + "description": "Deletes the specified Postgres role.", + "summary": "Delete a Postgres Role from a Branch.", + "path": "/api/2.0/postgres/{name=projects/*/branches/*/roles/*}", "has_required_positional_arguments": true, "launch_stage": "GA", "cli_launch_stage_display": "GA", "request": { - "pascal_name": "DeleteProjectRequest", + "pascal_name": "DeleteRoleRequest", "is_object": true, "required_fields": [ { "name": "name", - "description": "The full resource path of the project to delete.\nFormat: projects/{project_id}", + "description": "The full resource path of the role to delete.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", "required": true, "is_path": true, "entity": { @@ -169266,7 +171171,7 @@ "required_in_url_fields": [ { "name": "name", - "description": "The full resource path of the project to delete.\nFormat: projects/{project_id}", + "description": "The full resource path of the role to delete.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", "required": true, "is_path": true, "entity": { @@ -169282,7 +171187,7 @@ "all_fields": [ { "name": "name", - "description": "The full resource path of the project to delete.\nFormat: projects/{project_id}", + "description": "The full resource path of the role to delete.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", "required": true, "is_path": true, "entity": { @@ -169290,18 +171195,18 @@ } }, { - "name": "purge", - "description": "If true, permanently deletes the project (hard delete).\nIf false or unset, performs a soft delete.", + "name": "reassign_owned_to", + "description": "Reassign objects. If this is set, all objects owned by the role are\nreassigned to the role specified in this parameter.\n\nNOTE: setting this requires spinning up a compute to succeed, since it involves running\nSQL queries.", "is_query": true, "entity": { - "is_bool": true + "is_string": true } } ], "required_positional_arguments": [ { "name": "name", - "description": "The full resource path of the project to delete.\nFormat: projects/{project_id}", + "description": "The full resource path of the role to delete.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", "required": true, "is_path": true, "entity": { @@ -169323,20 +171228,21 @@ } }, { - "name": "DeleteRole", - "description": "Deletes the specified Postgres role.", - "summary": "Delete a Postgres Role from a Branch.", - "path": "/api/2.0/postgres/{name=projects/*/branches/*/roles/*}", + "name": "DeleteSnapshot", + "description": "Deletes the specified snapshot.", + "summary": "Delete a Snapshot.", + "path": "/api/2.0/postgres/{name=projects/*/snapshots/*}", + "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "GA", - "cli_launch_stage_display": "GA", + "launch_stage": "PRIVATE_PREVIEW", + "cli_launch_stage_display": "Private Preview", "request": { - "pascal_name": "DeleteRoleRequest", + "pascal_name": "DeleteSnapshotRequest", "is_object": true, "required_fields": [ { "name": "name", - "description": "The full resource path of the role to delete.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", + "description": "The resource name of the snapshot to delete.\nFormat: projects/{project_id}/snapshots/{snapshot_id}", "required": true, "is_path": true, "entity": { @@ -169347,7 +171253,7 @@ "required_in_url_fields": [ { "name": "name", - "description": "The full resource path of the role to delete.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", + "description": "The resource name of the snapshot to delete.\nFormat: projects/{project_id}/snapshots/{snapshot_id}", "required": true, "is_path": true, "entity": { @@ -169363,26 +171269,18 @@ "all_fields": [ { "name": "name", - "description": "The full resource path of the role to delete.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", + "description": "The resource name of the snapshot to delete.\nFormat: projects/{project_id}/snapshots/{snapshot_id}", "required": true, "is_path": true, "entity": { "is_string": true } - }, - { - "name": "reassign_owned_to", - "description": "Reassign objects. If this is set, all objects owned by the role are\nreassigned to the role specified in this parameter.\n\nNOTE: setting this requires spinning up a compute to succeed, since it involves running\nSQL queries.", - "is_query": true, - "entity": { - "is_string": true - } } ], "required_positional_arguments": [ { "name": "name", - "description": "The full resource path of the role to delete.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", + "description": "The resource name of the snapshot to delete.\nFormat: projects/{project_id}/snapshots/{snapshot_id}", "required": true, "is_path": true, "entity": { @@ -170254,6 +172152,132 @@ } ] }, + { + "name": "GetSnapshot", + "description": "Retrieves information about the specified snapshot.", + "summary": "Get a Snapshot.", + "path": "/api/2.0/postgres/{name=projects/*/snapshots/*}", + "is_crud_read": true, + "is_hidden_cli": true, + "has_required_positional_arguments": true, + "launch_stage": "PRIVATE_PREVIEW", + "cli_launch_stage_display": "Private Preview", + "request": { + "pascal_name": "GetSnapshotRequest", + "is_object": true, + "required_fields": [ + { + "name": "name", + "description": "The resource name of the snapshot to retrieve.\nFormat: projects/{project_id}/snapshots/{snapshot_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_in_url_fields": [ + { + "name": "name", + "description": "The resource name of the snapshot to retrieve.\nFormat: projects/{project_id}/snapshots/{snapshot_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + "response": { + "pascal_name": "Snapshot", + "is_object": true + }, + "all_fields": [ + { + "name": "name", + "description": "The resource name of the snapshot to retrieve.\nFormat: projects/{project_id}/snapshots/{snapshot_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_positional_arguments": [ + { + "name": "name", + "description": "The resource name of the snapshot to retrieve.\nFormat: projects/{project_id}/snapshots/{snapshot_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + { + "name": "GetSnapshotSchedule", + "description": "Retrieves the snapshot schedule for a branch. A branch with no configured\nschedule returns an empty schedule (not NOT_FOUND).", + "summary": "Get a Snapshot Schedule.", + "path": "/api/2.0/postgres/{name=projects/*/branches/*/snapshot-schedule}", + "is_crud_read": true, + "is_hidden_cli": true, + "has_required_positional_arguments": true, + "launch_stage": "PRIVATE_PREVIEW", + "cli_launch_stage_display": "Private Preview", + "request": { + "pascal_name": "GetSnapshotScheduleRequest", + "is_object": true, + "required_fields": [ + { + "name": "name", + "description": "The resource name of the branch's snapshot schedule.\nFormat: projects/{project_id}/branches/{branch_id}/snapshot-schedule", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_in_url_fields": [ + { + "name": "name", + "description": "The resource name of the branch's snapshot schedule.\nFormat: projects/{project_id}/branches/{branch_id}/snapshot-schedule", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + "response": { + "pascal_name": "SnapshotSchedule", + "is_object": true + }, + "all_fields": [ + { + "name": "name", + "description": "The resource name of the branch's snapshot schedule.\nFormat: projects/{project_id}/branches/{branch_id}/snapshot-schedule", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_positional_arguments": [ + { + "name": "name", + "description": "The resource name of the branch's snapshot schedule.\nFormat: projects/{project_id}/branches/{branch_id}/snapshot-schedule", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, { "name": "GetSyncedTable", "description": "Get a Synced Table.", @@ -170917,6 +172941,96 @@ } } }, + { + "name": "ListSnapshots", + "description": "Returns a paginated list of snapshots in the project.", + "summary": "List Snapshots.", + "path": "/api/2.0/postgres/{parent=projects/*}/snapshots", + "is_hidden_cli": true, + "has_required_positional_arguments": true, + "launch_stage": "PRIVATE_PREVIEW", + "cli_launch_stage_display": "Private Preview", + "request": { + "pascal_name": "ListSnapshotsRequest", + "is_object": true, + "required_fields": [ + { + "name": "parent", + "description": "The project that owns the snapshots.\nFormat: projects/{project_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_in_url_fields": [ + { + "name": "parent", + "description": "The project that owns the snapshots.\nFormat: projects/{project_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + "response": { + "pascal_name": "ListSnapshotsResponse", + "is_object": true + }, + "all_fields": [ + { + "name": "page_size", + "description": "Maximum number of snapshots to return per page.", + "is_query": true, + "entity": { + "is_int": true + } + }, + { + "name": "page_token", + "description": "Page token from a previous response; omit for the first page.", + "is_query": true, + "entity": { + "is_string": true + } + }, + { + "name": "parent", + "description": "The project that owns the snapshots.\nFormat: projects/{project_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_positional_arguments": [ + { + "name": "parent", + "description": "The project that owns the snapshots.\nFormat: projects/{project_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "pagination": { + "token": { + "poll_field": { + "name": "page_token", + "description": "Page token from a previous response; omit for the first page.", + "is_query": true, + "entity": { + "is_string": true + } + } + } + } + }, { "name": "UndeleteBranch", "description": "Undeletes the specified database branch.", @@ -171953,23 +174067,282 @@ } }, { - "name": "UpdateProject", - "description": "Updates the specified database project.", - "summary": "Update a Project.", - "path": "/api/2.0/postgres/{name=projects/*}", + "name": "UpdateProject", + "description": "Updates the specified database project.", + "summary": "Update a Project.", + "path": "/api/2.0/postgres/{name=projects/*}", + "can_use_json": true, + "has_required_positional_arguments": true, + "launch_stage": "GA", + "cli_launch_stage_display": "GA", + "request": { + "pascal_name": "UpdateProjectRequest", + "is_object": true, + "has_field_mask": true, + "has_required_request_body_fields": true, + "required_fields": [ + { + "name": "name", + "description": "Output only. The full resource path of the project.\nFormat: projects/{project_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "project", + "description": "The Project to update.\n\nThe project's `name` field is used to identify the project to update.\nFormat: projects/{project_id}", + "required": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "Project", + "is_object": true + } + }, + { + "name": "update_mask", + "description": "The list of fields to update.", + "required": true, + "is_query": true, + "entity": { + "is_field_mask": true + } + } + ], + "required_in_url_fields": [ + { + "name": "name", + "description": "Output only. The full resource path of the project.\nFormat: projects/{project_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "update_mask", + "description": "The list of fields to update.", + "required": true, + "is_query": true, + "entity": { + "is_field_mask": true + } + } + ], + "required_request_body_fields": [ + { + "name": "project", + "description": "The Project to update.\n\nThe project's `name` field is used to identify the project to update.\nFormat: projects/{project_id}", + "required": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "Project", + "is_object": true + } + } + ] + }, + "request_body_field": { + "name": "project", + "description": "The Project to update.\n\nThe project's `name` field is used to identify the project to update.\nFormat: projects/{project_id}", + "required": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "Project", + "is_object": true + } + }, + "response": { + "pascal_name": "Operation", + "is_object": true + }, + "all_fields": [ + { + "name": "name", + "description": "Output only. The full resource path of the project.\nFormat: projects/{project_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "project", + "description": "The Project to update.\n\nThe project's `name` field is used to identify the project to update.\nFormat: projects/{project_id}", + "required": true, + "is_request_body_field": true, + "entity": { + "pascal_name": "Project", + "is_object": true + } + }, + { + "name": "update_mask", + "description": "The list of fields to update.", + "required": true, + "is_query": true, + "entity": { + "is_field_mask": true + } + }, + { + "name": "create_time", + "description": "A timestamp indicating when the project was created.", + "is_output_only": true, + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "is_timestamp": true + } + }, + { + "name": "delete_time", + "description": "A timestamp indicating when the project was soft-deleted.\nEmpty if the project is not deleted, otherwise set to a timestamp in the past.", + "is_output_only": true, + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "is_timestamp": true + } + }, + { + "name": "initial_branch_spec", + "description": "Configuration for the initial default branch created as part of project creation.\nAllows overriding branch protection. These settings only apply at creation time\nand do not affect resources created after project creation.", + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "pascal_name": "InitialBranchSpec", + "is_object": true + } + }, + { + "name": "initial_endpoint_spec", + "description": "Configuration settings for the initial Read/Write endpoint created inside the initial branch for a newly\ncreated project. If omitted, the initial endpoint created will have default settings, without high availability\nconfigured. This field does not apply to any endpoints created after project creation. Use\nspec.default_endpoint_settings to configure default settings for endpoints created after project creation.", + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "pascal_name": "InitialEndpointSpec", + "is_object": true + } + }, + { + "name": "name", + "description": "Output only. The full resource path of the project.\nFormat: projects/{project_id}", + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "project_id", + "description": "The part of the name, chosen by the user when the resource was created.", + "is_output_only": true, + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "purge_time", + "description": "A timestamp indicating when the project is scheduled for permanent deletion.\nEmpty if the project is not deleted, otherwise set to a timestamp in the future.", + "is_output_only": true, + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "is_timestamp": true + } + }, + { + "name": "spec", + "description": "The spec contains the project configuration, including display_name, pg_version (Postgres version), history_retention_duration, and default_endpoint_settings.", + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "pascal_name": "ProjectSpec", + "is_object": true + } + }, + { + "name": "status", + "description": "The current status of a Project.", + "is_output_only": true, + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "pascal_name": "ProjectStatus", + "is_object": true + } + }, + { + "name": "uid", + "description": "System-generated unique ID for the project.", + "is_output_only": true, + "is_request_body_field": true, + "entity": { + "is_string": true + } + }, + { + "name": "update_time", + "description": "A timestamp indicating when the project was last updated.", + "is_output_only": true, + "is_request_body_field": true, + "is_optional_object": true, + "entity": { + "is_timestamp": true + } + } + ], + "required_positional_arguments": [ + { + "name": "name", + "description": "Output only. The full resource path of the project.\nFormat: projects/{project_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + }, + { + "name": "update_mask", + "description": "The list of fields to update.", + "required": true, + "is_query": true, + "entity": { + "is_field_mask": true + } + } + ], + "long_running_operation": { + "get_operation": { + "kebab_name": "get-operation", + "pascal_name": "GetOperation", + "request": { + "pascal_name": "GetOperationRequest" + } + }, + "response_type": {} + } + }, + { + "name": "UpdateRole", + "description": "Update a role for a branch.", + "summary": "Update a Postgres Role for a Branch.", + "path": "/api/2.0/postgres/{name=projects/*/branches/*/roles/*}", "can_use_json": true, "has_required_positional_arguments": true, "launch_stage": "GA", "cli_launch_stage_display": "GA", "request": { - "pascal_name": "UpdateProjectRequest", + "pascal_name": "UpdateRoleRequest", "is_object": true, "has_field_mask": true, "has_required_request_body_fields": true, "required_fields": [ { "name": "name", - "description": "Output only. The full resource path of the project.\nFormat: projects/{project_id}", + "description": "Output only. The full resource path of the role.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", "required": true, "is_path": true, "entity": { @@ -171977,12 +174350,12 @@ } }, { - "name": "project", - "description": "The Project to update.\n\nThe project's `name` field is used to identify the project to update.\nFormat: projects/{project_id}", + "name": "role", + "description": "The Postgres Role to update.\n\nThe role's `name` field is used to identify the role to update.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", "required": true, "is_request_body_field": true, "entity": { - "pascal_name": "Project", + "pascal_name": "Role", "is_object": true } }, @@ -171999,7 +174372,7 @@ "required_in_url_fields": [ { "name": "name", - "description": "Output only. The full resource path of the project.\nFormat: projects/{project_id}", + "description": "Output only. The full resource path of the role.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", "required": true, "is_path": true, "entity": { @@ -172018,24 +174391,24 @@ ], "required_request_body_fields": [ { - "name": "project", - "description": "The Project to update.\n\nThe project's `name` field is used to identify the project to update.\nFormat: projects/{project_id}", + "name": "role", + "description": "The Postgres Role to update.\n\nThe role's `name` field is used to identify the role to update.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", "required": true, "is_request_body_field": true, "entity": { - "pascal_name": "Project", + "pascal_name": "Role", "is_object": true } } ] }, "request_body_field": { - "name": "project", - "description": "The Project to update.\n\nThe project's `name` field is used to identify the project to update.\nFormat: projects/{project_id}", + "name": "role", + "description": "The Postgres Role to update.\n\nThe role's `name` field is used to identify the role to update.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", "required": true, "is_request_body_field": true, "entity": { - "pascal_name": "Project", + "pascal_name": "Role", "is_object": true } }, @@ -172046,7 +174419,7 @@ "all_fields": [ { "name": "name", - "description": "Output only. The full resource path of the project.\nFormat: projects/{project_id}", + "description": "Output only. The full resource path of the role.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", "required": true, "is_path": true, "entity": { @@ -172054,12 +174427,12 @@ } }, { - "name": "project", - "description": "The Project to update.\n\nThe project's `name` field is used to identify the project to update.\nFormat: projects/{project_id}", + "name": "role", + "description": "The Postgres Role to update.\n\nThe role's `name` field is used to identify the role to update.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", "required": true, "is_request_body_field": true, "entity": { - "pascal_name": "Project", + "pascal_name": "Role", "is_object": true } }, @@ -172074,17 +174447,6 @@ }, { "name": "create_time", - "description": "A timestamp indicating when the project was created.", - "is_output_only": true, - "is_request_body_field": true, - "is_optional_object": true, - "entity": { - "is_timestamp": true - } - }, - { - "name": "delete_time", - "description": "A timestamp indicating when the project was soft-deleted.\nEmpty if the project is not deleted, otherwise set to a timestamp in the past.", "is_output_only": true, "is_request_body_field": true, "is_optional_object": true, @@ -172092,37 +174454,17 @@ "is_timestamp": true } }, - { - "name": "initial_branch_spec", - "description": "Configuration for the initial default branch created as part of project creation.\nAllows overriding branch protection. These settings only apply at creation time\nand do not affect resources created after project creation.", - "is_request_body_field": true, - "is_optional_object": true, - "entity": { - "pascal_name": "InitialBranchSpec", - "is_object": true - } - }, - { - "name": "initial_endpoint_spec", - "description": "Configuration settings for the initial Read/Write endpoint created inside the initial branch for a newly\ncreated project. If omitted, the initial endpoint created will have default settings, without high availability\nconfigured. This field does not apply to any endpoints created after project creation. Use\nspec.default_endpoint_settings to configure default settings for endpoints created after project creation.", - "is_request_body_field": true, - "is_optional_object": true, - "entity": { - "pascal_name": "InitialEndpointSpec", - "is_object": true - } - }, { "name": "name", - "description": "Output only. The full resource path of the project.\nFormat: projects/{project_id}", + "description": "Output only. The full resource path of the role.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", "is_request_body_field": true, "entity": { "is_string": true } }, { - "name": "project_id", - "description": "The part of the name, chosen by the user when the resource was created.", + "name": "parent", + "description": "The Branch where this Role exists.\nFormat: projects/{project_id}/branches/{branch_id}", "is_output_only": true, "is_request_body_field": true, "entity": { @@ -172130,48 +174472,37 @@ } }, { - "name": "purge_time", - "description": "A timestamp indicating when the project is scheduled for permanent deletion.\nEmpty if the project is not deleted, otherwise set to a timestamp in the future.", + "name": "role_id", + "description": "The part of the name, chosen by the user when the resource was created.", "is_output_only": true, "is_request_body_field": true, - "is_optional_object": true, "entity": { - "is_timestamp": true + "is_string": true } }, { "name": "spec", - "description": "The spec contains the project configuration, including display_name, pg_version (Postgres version), history_retention_duration, and default_endpoint_settings.", + "description": "The spec contains the role configuration, including identity type, authentication method, and role attributes.", "is_request_body_field": true, "is_optional_object": true, "entity": { - "pascal_name": "ProjectSpec", + "pascal_name": "RoleRoleSpec", "is_object": true } }, { "name": "status", - "description": "The current status of a Project.", + "description": "Current status of the role, including its identity type, authentication method, and role attributes.", "is_output_only": true, "is_request_body_field": true, "is_optional_object": true, "entity": { - "pascal_name": "ProjectStatus", + "pascal_name": "RoleRoleStatus", "is_object": true } }, - { - "name": "uid", - "description": "System-generated unique ID for the project.", - "is_output_only": true, - "is_request_body_field": true, - "entity": { - "is_string": true - } - }, { "name": "update_time", - "description": "A timestamp indicating when the project was last updated.", "is_output_only": true, "is_request_body_field": true, "is_optional_object": true, @@ -172183,7 +174514,7 @@ "required_positional_arguments": [ { "name": "name", - "description": "Output only. The full resource path of the project.\nFormat: projects/{project_id}", + "description": "Output only. The full resource path of the role.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", "required": true, "is_path": true, "entity": { @@ -172212,23 +174543,24 @@ } }, { - "name": "UpdateRole", - "description": "Update a role for a branch.", - "summary": "Update a Postgres Role for a Branch.", - "path": "/api/2.0/postgres/{name=projects/*/branches/*/roles/*}", + "name": "UpdateSnapshotSchedule", + "description": "Sets the snapshot schedule for a branch. The `schedule` field is replaced\nwholesale; an empty schedule disables automatic snapshots.", + "summary": "Update a Snapshot Schedule.", + "path": "/api/2.0/postgres/{name=projects/*/branches/*/snapshot-schedule}", "can_use_json": true, + "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "GA", - "cli_launch_stage_display": "GA", + "launch_stage": "PRIVATE_PREVIEW", + "cli_launch_stage_display": "Private Preview", "request": { - "pascal_name": "UpdateRoleRequest", + "pascal_name": "UpdateSnapshotScheduleRequest", "is_object": true, "has_field_mask": true, "has_required_request_body_fields": true, "required_fields": [ { "name": "name", - "description": "Output only. The full resource path of the role.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", + "description": "The resource name of the branch's snapshot schedule.\nFormat: projects/{project_id}/branches/{branch_id}/snapshot-schedule", "required": true, "is_path": true, "entity": { @@ -172236,18 +174568,18 @@ } }, { - "name": "role", - "description": "The Postgres Role to update.\n\nThe role's `name` field is used to identify the role to update.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", + "name": "snapshot_schedule", + "description": "The snapshot schedule to set. Its `name` identifies the branch.\nFormat: projects/{project_id}/branches/{branch_id}/snapshot-schedule", "required": true, "is_request_body_field": true, "entity": { - "pascal_name": "Role", + "pascal_name": "SnapshotSchedule", "is_object": true } }, { "name": "update_mask", - "description": "The list of fields to update.", + "description": "Fields to update. The only updatable path is `schedule`, which replaces the\nentire set of cadences.", "required": true, "is_query": true, "entity": { @@ -172258,7 +174590,7 @@ "required_in_url_fields": [ { "name": "name", - "description": "Output only. The full resource path of the role.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", + "description": "The resource name of the branch's snapshot schedule.\nFormat: projects/{project_id}/branches/{branch_id}/snapshot-schedule", "required": true, "is_path": true, "entity": { @@ -172267,7 +174599,7 @@ }, { "name": "update_mask", - "description": "The list of fields to update.", + "description": "Fields to update. The only updatable path is `schedule`, which replaces the\nentire set of cadences.", "required": true, "is_query": true, "entity": { @@ -172277,24 +174609,24 @@ ], "required_request_body_fields": [ { - "name": "role", - "description": "The Postgres Role to update.\n\nThe role's `name` field is used to identify the role to update.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", + "name": "snapshot_schedule", + "description": "The snapshot schedule to set. Its `name` identifies the branch.\nFormat: projects/{project_id}/branches/{branch_id}/snapshot-schedule", "required": true, "is_request_body_field": true, "entity": { - "pascal_name": "Role", + "pascal_name": "SnapshotSchedule", "is_object": true } } ] }, "request_body_field": { - "name": "role", - "description": "The Postgres Role to update.\n\nThe role's `name` field is used to identify the role to update.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", + "name": "snapshot_schedule", + "description": "The snapshot schedule to set. Its `name` identifies the branch.\nFormat: projects/{project_id}/branches/{branch_id}/snapshot-schedule", "required": true, "is_request_body_field": true, "entity": { - "pascal_name": "Role", + "pascal_name": "SnapshotSchedule", "is_object": true } }, @@ -172305,7 +174637,7 @@ "all_fields": [ { "name": "name", - "description": "Output only. The full resource path of the role.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", + "description": "The resource name of the branch's snapshot schedule.\nFormat: projects/{project_id}/branches/{branch_id}/snapshot-schedule", "required": true, "is_path": true, "entity": { @@ -172313,94 +174645,49 @@ } }, { - "name": "role", - "description": "The Postgres Role to update.\n\nThe role's `name` field is used to identify the role to update.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", + "name": "snapshot_schedule", + "description": "The snapshot schedule to set. Its `name` identifies the branch.\nFormat: projects/{project_id}/branches/{branch_id}/snapshot-schedule", "required": true, "is_request_body_field": true, "entity": { - "pascal_name": "Role", + "pascal_name": "SnapshotSchedule", "is_object": true } }, { "name": "update_mask", - "description": "The list of fields to update.", + "description": "Fields to update. The only updatable path is `schedule`, which replaces the\nentire set of cadences.", "required": true, "is_query": true, "entity": { "is_field_mask": true } }, - { - "name": "create_time", - "is_output_only": true, - "is_request_body_field": true, - "is_optional_object": true, - "entity": { - "is_timestamp": true - } - }, { "name": "name", - "description": "Output only. The full resource path of the role.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", - "is_request_body_field": true, - "entity": { - "is_string": true - } - }, - { - "name": "parent", - "description": "The Branch where this Role exists.\nFormat: projects/{project_id}/branches/{branch_id}", - "is_output_only": true, + "description": "The resource name of the branch's snapshot schedule.\nFormat: projects/{project_id}/branches/{branch_id}/snapshot-schedule", "is_request_body_field": true, "entity": { "is_string": true } }, { - "name": "role_id", - "description": "The part of the name, chosen by the user when the resource was created.", - "is_output_only": true, - "is_request_body_field": true, - "entity": { - "is_string": true - } - }, - { - "name": "spec", - "description": "The spec contains the role configuration, including identity type, authentication method, and role attributes.", - "is_request_body_field": true, - "is_optional_object": true, - "entity": { - "pascal_name": "RoleRoleSpec", - "is_object": true - } - }, - { - "name": "status", - "description": "Current status of the role, including its identity type, authentication method, and role attributes.", - "is_output_only": true, - "is_request_body_field": true, - "is_optional_object": true, - "entity": { - "pascal_name": "RoleRoleStatus", - "is_object": true - } - }, - { - "name": "update_time", - "is_output_only": true, + "name": "schedule", + "description": "The cadences at which automatic snapshots are taken. Update replaces the\nwhole set; an empty set disables automatic snapshots. Order is not\nsignificant. When several cadences fire together, one snapshot is taken,\nretained for the longest of their retentions.", "is_request_body_field": true, - "is_optional_object": true, "entity": { - "is_timestamp": true + "pascal_name": "ScheduleCadenceList", + "array_value": { + "pascal_name": "ScheduleCadence", + "is_object": true + } } } ], "required_positional_arguments": [ { "name": "name", - "description": "Output only. The full resource path of the role.\nFormat: projects/{project_id}/branches/{branch_id}/roles/{role_id}", + "description": "The resource name of the branch's snapshot schedule.\nFormat: projects/{project_id}/branches/{branch_id}/snapshot-schedule", "required": true, "is_path": true, "entity": { @@ -172409,7 +174696,7 @@ }, { "name": "update_mask", - "description": "The list of fields to update.", + "description": "Fields to update. The only updatable path is `schedule`, which replaces the\nentire set of cadences.", "required": true, "is_query": true, "entity": { @@ -191721,10 +194008,8 @@ }, "is_accounts": true, "docs_group": "settings", - "launch_stage": "PUBLIC_PREVIEW", - "cli_launch_stage_label": "*Public Preview*", - "cli_launch_stage_banner": "This command is in Public Preview and may change without notice.", - "cli_launch_stage_display": "Public Preview", + "launch_stage": "GA", + "cli_launch_stage_display": "GA", "list": { "request": { "pascal_name": "ListAccountSettingsMetadataRequest" @@ -191737,10 +194022,8 @@ "summary": "Get an account setting.", "path": "/api/2.1/accounts/{account_id}/settings/{name}", "has_required_positional_arguments": true, - "launch_stage": "PUBLIC_PREVIEW", - "cli_launch_stage_label": "*Public Preview*", - "cli_launch_stage_banner": "This command is in Public Preview and may change without notice.", - "cli_launch_stage_display": "Public Preview", + "launch_stage": "GA", + "cli_launch_stage_display": "GA", "request": { "pascal_name": "GetPublicAccountSettingRequest", "is_object": true, @@ -191895,10 +194178,8 @@ "summary": "List valid setting keys and their metadata.", "path": "/api/2.1/accounts/{account_id}/settings-metadata", "has_required_positional_arguments": true, - "launch_stage": "PUBLIC_PREVIEW", - "cli_launch_stage_label": "*Public Preview*", - "cli_launch_stage_banner": "This command is in Public Preview and may change without notice.", - "cli_launch_stage_display": "Public Preview", + "launch_stage": "GA", + "cli_launch_stage_display": "GA", "request": { "pascal_name": "ListAccountSettingsMetadataRequest", "is_object": true @@ -192036,10 +194317,8 @@ "path": "/api/2.1/accounts/{account_id}/settings/{name}", "can_use_json": true, "has_required_positional_arguments": true, - "launch_stage": "PUBLIC_PREVIEW", - "cli_launch_stage_label": "*Public Preview*", - "cli_launch_stage_banner": "This command is in Public Preview and may change without notice.", - "cli_launch_stage_display": "Public Preview", + "launch_stage": "GA", + "cli_launch_stage_display": "GA", "request": { "pascal_name": "PatchPublicAccountSettingRequest", "is_object": true, @@ -211059,10 +213338,11 @@ "summary": "Create a direct group membership.", "path": "/api/2.0/identity/groups/{group_id}/direct-members", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "CreateDirectGroupMemberProxyRequest", "is_object": true, @@ -211316,10 +213596,11 @@ "summary": "Create a group in the account.", "path": "/api/2.0/identity/groups", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "CreateGroupProxyRequest", "is_object": true, @@ -211416,10 +213697,11 @@ "summary": "Create a service principal in the account.", "path": "/api/2.0/identity/service-principals", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "CreateServicePrincipalProxyRequest", "is_object": true, @@ -211742,10 +214024,11 @@ "summary": "Create a user in the account.", "path": "/api/2.0/identity/users", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "CreateUserProxyRequest", "is_object": true, @@ -212127,7 +214410,7 @@ }, { "name": "CreateWorkspaceAssignmentDetailProxy", - "description": "Creates a workspace assignment detail for a principal in the calling workspace. Entitlements\nare granted one at a time rather than atomically. If the request fails partway through, the\nprincipal stays assigned to the workspace with only some of the requested entitlements. Get the\nassignment detail afterwards to confirm which entitlements were granted.", + "description": "Creates a workspace assignment detail for a principal in the calling workspace.", "summary": "Create a workspace assignment detail for a workspace.", "path": "/api/2.0/identity/workspace-assignment-details", "can_use_json": true, @@ -212386,10 +214669,11 @@ "summary": "Create a workspace assignment for a workspace.", "path": "/api/2.0/identity/workspace-assignments", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "CreateWorkspaceAssignmentProxyRequest", "is_object": true, @@ -212641,10 +214925,11 @@ "description": "Deletes a group membership (unassigns a principal from a group).", "summary": "Delete a direct group membership.", "path": "/api/2.0/identity/groups/{group_id}/direct-members/{principal_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "DeleteDirectGroupMemberProxyRequest", "is_object": true, @@ -212738,10 +215023,11 @@ "description": "Deletes a group by its internal ID from the Databricks\naccount that parents the calling workspace.", "summary": "Delete a group in the account.", "path": "/api/2.0/identity/groups/{group_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "DeleteGroupProxyRequest", "is_object": true, @@ -212799,10 +215085,11 @@ "description": "Deletes a service principal by its internal ID\nfrom the Databricks account that parents the calling workspace.", "summary": "Delete a service principal in the account.", "path": "/api/2.0/identity/service-principals/{service_principal_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "DeleteServicePrincipalProxyRequest", "is_object": true, @@ -212860,10 +215147,11 @@ "description": "Deletes a user by its internal ID from the Databricks\naccount that parents the calling workspace.", "summary": "Delete a user in the account.", "path": "/api/2.0/identity/users/{user_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "DeleteUserProxyRequest", "is_object": true, @@ -212982,10 +215270,11 @@ "description": "Deletes a workspace assignment for a principal in the calling workspace, revoking all of\nits entitlements. Entitlements are revoked one at a time rather than atomically. If the request\nfails partway through, the principal stays assigned with some of its original entitlements.\nRetrying is safe.", "summary": "Delete a workspace assignment for a workspace.", "path": "/api/2.0/identity/workspace-assignments/{principal_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "DeleteWorkspaceAssignmentProxyRequest", "is_object": true, @@ -213043,10 +215332,11 @@ "description": "Gets a provisioned direct member of a group.", "summary": "Get a direct group member.", "path": "/api/2.0/identity/groups/{group_id}/direct-members/{principal_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "GetDirectGroupMemberProxyRequest", "is_object": true, @@ -213159,15 +215449,205 @@ } ] }, + { + "name": "GetExternalGroupProxy", + "description": "Retrieves an external group with the given external ID from the customer's\nIdP. If the group does not exist, it will be created in the account. If the\ncustomer is not onboarded onto Automatic Identity Management (AIM), this will\nreturn an error. Workspace-scoped variant for workspace-authenticated callers.", + "summary": "Get an external group in the account.", + "path": "/api/2.0/identity/{name=external-groups/*}", + "has_required_positional_arguments": true, + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", + "request": { + "pascal_name": "GetExternalGroupProxyRequest", + "is_object": true, + "required_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external group.\nFormat: external-groups/{external_group_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_in_url_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external group.\nFormat: external-groups/{external_group_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + "response": { + "pascal_name": "ExternalGroup", + "is_object": true + }, + "all_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external group.\nFormat: external-groups/{external_group_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_positional_arguments": [ + { + "name": "name", + "description": "Required. The resource name of the external group.\nFormat: external-groups/{external_group_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + { + "name": "GetExternalServicePrincipalProxy", + "description": "Retrieves an external service principal with the given external ID from the\ncustomer's IdP. If the service principal does not exist, it will be created.\nIf the customer is not onboarded onto Automatic Identity Management (AIM),\nthis will return an error. Workspace-scoped variant for workspace-authenticated\ncallers.", + "summary": "Get an external service principal in the account.", + "path": "/api/2.0/identity/{name=external-service-principals/*}", + "has_required_positional_arguments": true, + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", + "request": { + "pascal_name": "GetExternalServicePrincipalProxyRequest", + "is_object": true, + "required_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external service principal.\nFormat: external-service-principals/{external_service_principal_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_in_url_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external service principal.\nFormat: external-service-principals/{external_service_principal_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + "response": { + "pascal_name": "ExternalServicePrincipal", + "is_object": true + }, + "all_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external service principal.\nFormat: external-service-principals/{external_service_principal_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_positional_arguments": [ + { + "name": "name", + "description": "Required. The resource name of the external service principal.\nFormat: external-service-principals/{external_service_principal_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + { + "name": "GetExternalUserProxy", + "description": "Retrieves an external user with the given external ID from the customer's\nIdP. If the user does not exist, it will be created. If the customer is not\nonboarded onto Automatic Identity Management (AIM), this will return an error.\nWorkspace-scoped variant for workspace-authenticated callers.", + "summary": "Get an external user in the account.", + "path": "/api/2.0/identity/{name=external-users/*}", + "has_required_positional_arguments": true, + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", + "request": { + "pascal_name": "GetExternalUserProxyRequest", + "is_object": true, + "required_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external user.\nFormat: external-users/{external_user_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_in_url_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external user.\nFormat: external-users/{external_user_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, + "response": { + "pascal_name": "ExternalUser", + "is_object": true + }, + "all_fields": [ + { + "name": "name", + "description": "Required. The resource name of the external user.\nFormat: external-users/{external_user_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ], + "required_positional_arguments": [ + { + "name": "name", + "description": "Required. The resource name of the external user.\nFormat: external-users/{external_user_id}", + "required": true, + "is_path": true, + "entity": { + "is_string": true + } + } + ] + }, { "name": "GetGroupProxy", "description": "Fetches a group by its internal ID from the Databricks\naccount that parents the calling workspace.", "summary": "Get a group in the account.", "path": "/api/2.0/identity/groups/{group_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "GetGroupProxyRequest", "is_object": true, @@ -213226,10 +215706,11 @@ "description": "Fetches a service principal by its internal ID\nfrom the Databricks account that parents the calling workspace.", "summary": "Get a service principal in the account.", "path": "/api/2.0/identity/service-principals/{service_principal_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "GetServicePrincipalProxyRequest", "is_object": true, @@ -213345,10 +215826,11 @@ "description": "Fetches a user by its internal ID from the Databricks account\nthat parents the calling workspace.", "summary": "Get a user in the account.", "path": "/api/2.0/identity/users/{user_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "GetUserProxyRequest", "is_object": true, @@ -213646,10 +216128,11 @@ "description": "Returns the assignment for a principal in the calling workspace.", "summary": "Get a workspace assignment for a principal.", "path": "/api/2.0/identity/workspace-assignments/{principal_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "GetWorkspaceAssignmentProxyRequest", "is_object": true, @@ -213731,10 +216214,11 @@ "description": "Returns the identity details for a principal in a workspace.", "summary": "Get workspace identity details for a principal.", "path": "/api/2.0/identity/workspace-identity-details/{principal_id}", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "GetWorkspaceIdentityDetailRequest", "is_object": true, @@ -213793,10 +216277,11 @@ "description": "Lists provisioned direct members of a group with their membership source (internal or from identity provider).", "summary": "List direct group members.", "path": "/api/2.0/identity/groups/{group_id}/direct-members", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "ListDirectGroupMembersProxyRequest", "is_object": true, @@ -213839,7 +216324,7 @@ }, { "name": "page_size", - "description": "The maximum number of members to return. The service may return fewer than this value.\nIf not provided, defaults to 1000 (also the maximum allowed).", + "description": "The maximum number of members to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", "is_query": true, "entity": { "is_int": true @@ -213883,10 +216368,11 @@ "description": "Lists the groups in the Databricks account that parents\nthe calling workspace, returning one page per call. Supports filtering by group name or external ID.", "summary": "List groups in the account.", "path": "/api/2.0/identity/groups", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "ListGroupsProxyRequest", "is_object": true @@ -213906,7 +216392,7 @@ }, { "name": "page_size", - "description": "The maximum number of groups to return. The service may return fewer than this value.", + "description": "The maximum number of groups to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", "is_query": true, "entity": { "is_int": true @@ -213939,10 +216425,11 @@ "description": "Lists the service principals in the Databricks\naccount that parents the calling workspace, returning one page per call. Supports filtering by\napplication ID or external ID.", "summary": "List service principals in the account.", "path": "/api/2.0/identity/service-principals", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "ListServicePrincipalsProxyRequest", "is_object": true @@ -213962,7 +216449,7 @@ }, { "name": "page_size", - "description": "The maximum number of SPs to return. The service may return fewer than this value.", + "description": "The maximum number of SPs to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", "is_query": true, "entity": { "is_int": true @@ -213995,10 +216482,11 @@ "description": "Lists all transitive parent groups of a principal.", "summary": "List all transitive parent groups of a principal.", "path": "/api/2.0/identity/principals/{principal_id}/transitive-parent-groups", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "ListTransitiveParentGroupsProxyRequest", "is_object": true, @@ -214032,7 +216520,7 @@ "all_fields": [ { "name": "page_size", - "description": "The maximum number of parent groups to return. The service may return fewer than this value.\nIf not provided, defaults to 1000 (also the maximum allowed).", + "description": "The maximum number of parent groups to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", "is_query": true, "entity": { "is_int": true @@ -214073,10 +216561,11 @@ "description": "Lists the users in the Databricks account that parents the\ncalling workspace, returning one page per call. Supports filtering by username or external ID.", "summary": "List users in the account.", "path": "/api/2.0/identity/users", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "ListUsersProxyRequest", "is_object": true @@ -214096,7 +216585,7 @@ }, { "name": "page_size", - "description": "The maximum number of users to return. The service may return fewer than this value.", + "description": "The maximum number of users to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", "is_query": true, "entity": { "is_int": true @@ -214144,7 +216633,7 @@ "all_fields": [ { "name": "page_size", - "description": "The maximum number of workspace assignment details to return. The service may return fewer than this value.", + "description": "The maximum number of workspace assignment details to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", "is_query": true, "entity": { "is_int": true @@ -214177,10 +216666,11 @@ "description": "Lists workspace assignments for the calling workspace. The response omits the\nper-principal entitlement fields (`entitlements` and `effective_entitlements`). To read the\nentitlements for a single principal, get that principal's assignment.", "summary": "List workspace assignments for a workspace.", "path": "/api/2.0/identity/workspace-assignments", - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "ListWorkspaceAssignmentsProxyRequest", "is_object": true @@ -214192,7 +216682,7 @@ "all_fields": [ { "name": "page_size", - "description": "The maximum number of workspace assignments to return. The service may return fewer than this value.", + "description": "The maximum number of workspace assignments to return. The service may return fewer than this value.\nIf not provided, defaults to 1000, which is also the maximum allowed. Requests for more than the maximum are clamped to 1000.", "is_query": true, "entity": { "is_int": true @@ -214421,10 +216911,11 @@ "summary": "Update a group in the account.", "path": "/api/2.0/identity/groups/{group_id}", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "UpdateGroupProxyRequest", "is_object": true, @@ -214597,10 +217088,11 @@ "summary": "Update a service principal in the account.", "path": "/api/2.0/identity/service-principals/{service_principal_id}", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "UpdateServicePrincipalProxyRequest", "is_object": true, @@ -214997,10 +217489,11 @@ "summary": "Update a user in the account.", "path": "/api/2.0/identity/users/{user_id}", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "UpdateUserProxyRequest", "is_object": true, @@ -215790,10 +218283,11 @@ "summary": "Update a workspace assignment for a workspace.", "path": "/api/2.0/identity/workspace-assignments/{principal_id}", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "UpdateWorkspaceAssignmentProxyRequest", "is_object": true, @@ -216121,10 +218615,11 @@ "summary": "Update workspace identity details for a principal.", "path": "/api/2.0/identity/workspace-identity-details/{principal_id}", "can_use_json": true, - "is_hidden_cli": true, "has_required_positional_arguments": true, - "launch_stage": "PRIVATE_PREVIEW", - "cli_launch_stage_display": "Private Preview", + "launch_stage": "PUBLIC_BETA", + "cli_launch_stage_label": "*Beta*", + "cli_launch_stage_banner": "This command is in Beta and may change without notice.", + "cli_launch_stage_display": "Beta", "request": { "pascal_name": "UpdateWorkspaceIdentityDetailRequest", "is_object": true, @@ -216526,10 +219021,8 @@ "name": "settingsv2" }, "docs_group": "settings", - "launch_stage": "PUBLIC_PREVIEW", - "cli_launch_stage_label": "*Public Preview*", - "cli_launch_stage_banner": "This command is in Public Preview and may change without notice.", - "cli_launch_stage_display": "Public Preview", + "launch_stage": "GA", + "cli_launch_stage_display": "GA", "list": { "request": { "pascal_name": "ListWorkspaceSettingsMetadataRequest" @@ -216543,10 +219036,8 @@ "path": "/api/2.1/settings/{name}", "is_crud_read": true, "has_required_positional_arguments": true, - "launch_stage": "PUBLIC_PREVIEW", - "cli_launch_stage_label": "*Public Preview*", - "cli_launch_stage_banner": "This command is in Public Preview and may change without notice.", - "cli_launch_stage_display": "Public Preview", + "launch_stage": "GA", + "cli_launch_stage_display": "GA", "request": { "pascal_name": "GetPublicWorkspaceSettingRequest", "is_object": true, @@ -216606,10 +219097,8 @@ "summary": "List valid setting keys and their metadata.", "path": "/api/2.1/settings-metadata", "has_required_positional_arguments": true, - "launch_stage": "PUBLIC_PREVIEW", - "cli_launch_stage_label": "*Public Preview*", - "cli_launch_stage_banner": "This command is in Public Preview and may change without notice.", - "cli_launch_stage_display": "Public Preview", + "launch_stage": "GA", + "cli_launch_stage_display": "GA", "request": { "pascal_name": "ListWorkspaceSettingsMetadataRequest", "is_object": true @@ -216656,10 +219145,8 @@ "path": "/api/2.1/settings/{name}", "can_use_json": true, "has_required_positional_arguments": true, - "launch_stage": "PUBLIC_PREVIEW", - "cli_launch_stage_label": "*Public Preview*", - "cli_launch_stage_banner": "This command is in Public Preview and may change without notice.", - "cli_launch_stage_display": "Public Preview", + "launch_stage": "GA", + "cli_launch_stage_display": "GA", "request": { "pascal_name": "PatchPublicWorkspaceSettingRequest", "is_object": true, @@ -217865,7 +220352,7 @@ }, { "key": "sharing", - "display_name": "Delta Sharing" + "display_name": "Open Sharing" }, { "key": "settings", diff --git a/.nextchanges/dependency-updates/bump-sdk-0.177.0.md b/.nextchanges/dependency-updates/bump-sdk-0.177.0.md new file mode 100644 index 00000000000..8db1c71608a --- /dev/null +++ b/.nextchanges/dependency-updates/bump-sdk-0.177.0.md @@ -0,0 +1 @@ +Bump `github.com/databricks/databricks-sdk-go` from v0.175.0 to v0.177.0. diff --git a/acceptance/bundle/refschema/out.fields.txt b/acceptance/bundle/refschema/out.fields.txt index de252dc4162..748939d3c56 100644 --- a/acceptance/bundle/refschema/out.fields.txt +++ b/acceptance/bundle/refschema/out.fields.txt @@ -409,6 +409,7 @@ resources.clusters.*.driver_instance_pool_id string ALL resources.clusters.*.driver_node_type_flexibility *compute.NodeTypeFlexibility ALL resources.clusters.*.driver_node_type_flexibility.alternate_node_type_ids []string ALL resources.clusters.*.driver_node_type_flexibility.alternate_node_type_ids[*] string ALL +resources.clusters.*.driver_node_type_flexibility.aws_context_id string ALL resources.clusters.*.driver_node_type_id string ALL resources.clusters.*.enable_elastic_disk bool ALL resources.clusters.*.enable_local_disk_encryption bool ALL @@ -530,6 +531,7 @@ resources.clusters.*.spec.driver_instance_pool_id string REMOTE resources.clusters.*.spec.driver_node_type_flexibility *compute.NodeTypeFlexibility REMOTE resources.clusters.*.spec.driver_node_type_flexibility.alternate_node_type_ids []string REMOTE resources.clusters.*.spec.driver_node_type_flexibility.alternate_node_type_ids[*] string REMOTE +resources.clusters.*.spec.driver_node_type_flexibility.aws_context_id string REMOTE resources.clusters.*.spec.driver_node_type_id string REMOTE resources.clusters.*.spec.enable_elastic_disk bool REMOTE resources.clusters.*.spec.enable_local_disk_encryption bool REMOTE @@ -585,6 +587,7 @@ resources.clusters.*.spec.use_ml_runtime bool REMOTE resources.clusters.*.spec.worker_node_type_flexibility *compute.NodeTypeFlexibility REMOTE resources.clusters.*.spec.worker_node_type_flexibility.alternate_node_type_ids []string REMOTE resources.clusters.*.spec.worker_node_type_flexibility.alternate_node_type_ids[*] string REMOTE +resources.clusters.*.spec.worker_node_type_flexibility.aws_context_id string REMOTE resources.clusters.*.spec.workload_type *compute.WorkloadType REMOTE resources.clusters.*.spec.workload_type.clients compute.ClientsTypes REMOTE resources.clusters.*.spec.workload_type.clients.jobs bool REMOTE @@ -606,6 +609,7 @@ resources.clusters.*.use_ml_runtime bool ALL resources.clusters.*.worker_node_type_flexibility *compute.NodeTypeFlexibility ALL resources.clusters.*.worker_node_type_flexibility.alternate_node_type_ids []string ALL resources.clusters.*.worker_node_type_flexibility.alternate_node_type_ids[*] string ALL +resources.clusters.*.worker_node_type_flexibility.aws_context_id string ALL resources.clusters.*.workload_type *compute.WorkloadType ALL resources.clusters.*.workload_type.clients compute.ClientsTypes ALL resources.clusters.*.workload_type.clients.jobs bool ALL @@ -867,6 +871,7 @@ resources.instance_pools.*.modified_status string INPUT resources.instance_pools.*.node_type_flexibility *compute.NodeTypeFlexibility ALL resources.instance_pools.*.node_type_flexibility.alternate_node_type_ids []string ALL resources.instance_pools.*.node_type_flexibility.alternate_node_type_ids[*] string ALL +resources.instance_pools.*.node_type_flexibility.aws_context_id string ALL resources.instance_pools.*.node_type_id string ALL resources.instance_pools.*.preloaded_docker_images []compute.DockerImage ALL resources.instance_pools.*.preloaded_docker_images[*] compute.DockerImage ALL @@ -955,6 +960,10 @@ resources.job_runs.*.state.user_cancelled_or_timedout bool REMOTE resources.job_runs.*.url string INPUT resources.jobs.*.budget_policy_id string ALL resources.jobs.*.continuous *jobs.Continuous ALL +resources.jobs.*.continuous.maintenance_window *jobs.MaintenanceWindow ALL +resources.jobs.*.continuous.maintenance_window.day_of_week jobs.DayOfWeek ALL +resources.jobs.*.continuous.maintenance_window.start_hour int ALL +resources.jobs.*.continuous.maintenance_window.timezone_id string ALL resources.jobs.*.continuous.pause_status jobs.PauseStatus ALL resources.jobs.*.continuous.task_retry_mode jobs.TaskRetryMode ALL resources.jobs.*.created_time int64 REMOTE @@ -1069,6 +1078,7 @@ resources.jobs.*.job_clusters[*].new_cluster.driver_instance_pool_id string ALL resources.jobs.*.job_clusters[*].new_cluster.driver_node_type_flexibility *compute.NodeTypeFlexibility ALL resources.jobs.*.job_clusters[*].new_cluster.driver_node_type_flexibility.alternate_node_type_ids []string ALL resources.jobs.*.job_clusters[*].new_cluster.driver_node_type_flexibility.alternate_node_type_ids[*] string ALL +resources.jobs.*.job_clusters[*].new_cluster.driver_node_type_flexibility.aws_context_id string ALL resources.jobs.*.job_clusters[*].new_cluster.driver_node_type_id string ALL resources.jobs.*.job_clusters[*].new_cluster.enable_elastic_disk bool ALL resources.jobs.*.job_clusters[*].new_cluster.enable_local_disk_encryption bool ALL @@ -1124,6 +1134,7 @@ resources.jobs.*.job_clusters[*].new_cluster.use_ml_runtime bool ALL resources.jobs.*.job_clusters[*].new_cluster.worker_node_type_flexibility *compute.NodeTypeFlexibility ALL resources.jobs.*.job_clusters[*].new_cluster.worker_node_type_flexibility.alternate_node_type_ids []string ALL resources.jobs.*.job_clusters[*].new_cluster.worker_node_type_flexibility.alternate_node_type_ids[*] string ALL +resources.jobs.*.job_clusters[*].new_cluster.worker_node_type_flexibility.aws_context_id string ALL resources.jobs.*.job_clusters[*].new_cluster.workload_type *compute.WorkloadType ALL resources.jobs.*.job_clusters[*].new_cluster.workload_type.clients compute.ClientsTypes ALL resources.jobs.*.job_clusters[*].new_cluster.workload_type.clients.jobs bool ALL @@ -1179,6 +1190,8 @@ resources.jobs.*.tasks[*].ai_runtime_task.mlflow_experiment_directory string ALL resources.jobs.*.tasks[*].ai_runtime_task.mlflow_run string ALL resources.jobs.*.tasks[*].alert_task *jobs.AlertTask ALL resources.jobs.*.tasks[*].alert_task.alert_id string ALL +resources.jobs.*.tasks[*].alert_task.parameters map[string]string ALL +resources.jobs.*.tasks[*].alert_task.parameters.* string ALL resources.jobs.*.tasks[*].alert_task.subscribers []jobs.AlertTaskSubscriber ALL resources.jobs.*.tasks[*].alert_task.subscribers[*] jobs.AlertTaskSubscriber ALL resources.jobs.*.tasks[*].alert_task.subscribers[*].destination_id string ALL @@ -1265,6 +1278,8 @@ resources.jobs.*.tasks[*].for_each_task.task.ai_runtime_task.mlflow_experiment_d resources.jobs.*.tasks[*].for_each_task.task.ai_runtime_task.mlflow_run string ALL resources.jobs.*.tasks[*].for_each_task.task.alert_task *jobs.AlertTask ALL resources.jobs.*.tasks[*].for_each_task.task.alert_task.alert_id string ALL +resources.jobs.*.tasks[*].for_each_task.task.alert_task.parameters map[string]string ALL +resources.jobs.*.tasks[*].for_each_task.task.alert_task.parameters.* string ALL resources.jobs.*.tasks[*].for_each_task.task.alert_task.subscribers []jobs.AlertTaskSubscriber ALL resources.jobs.*.tasks[*].for_each_task.task.alert_task.subscribers[*] jobs.AlertTaskSubscriber ALL resources.jobs.*.tasks[*].for_each_task.task.alert_task.subscribers[*].destination_id string ALL @@ -1425,6 +1440,7 @@ resources.jobs.*.tasks[*].for_each_task.task.new_cluster.driver_instance_pool_id resources.jobs.*.tasks[*].for_each_task.task.new_cluster.driver_node_type_flexibility *compute.NodeTypeFlexibility ALL resources.jobs.*.tasks[*].for_each_task.task.new_cluster.driver_node_type_flexibility.alternate_node_type_ids []string ALL resources.jobs.*.tasks[*].for_each_task.task.new_cluster.driver_node_type_flexibility.alternate_node_type_ids[*] string ALL +resources.jobs.*.tasks[*].for_each_task.task.new_cluster.driver_node_type_flexibility.aws_context_id string ALL resources.jobs.*.tasks[*].for_each_task.task.new_cluster.driver_node_type_id string ALL resources.jobs.*.tasks[*].for_each_task.task.new_cluster.enable_elastic_disk bool ALL resources.jobs.*.tasks[*].for_each_task.task.new_cluster.enable_local_disk_encryption bool ALL @@ -1480,6 +1496,7 @@ resources.jobs.*.tasks[*].for_each_task.task.new_cluster.use_ml_runtime bool ALL resources.jobs.*.tasks[*].for_each_task.task.new_cluster.worker_node_type_flexibility *compute.NodeTypeFlexibility ALL resources.jobs.*.tasks[*].for_each_task.task.new_cluster.worker_node_type_flexibility.alternate_node_type_ids []string ALL resources.jobs.*.tasks[*].for_each_task.task.new_cluster.worker_node_type_flexibility.alternate_node_type_ids[*] string ALL +resources.jobs.*.tasks[*].for_each_task.task.new_cluster.worker_node_type_flexibility.aws_context_id string ALL resources.jobs.*.tasks[*].for_each_task.task.new_cluster.workload_type *compute.WorkloadType ALL resources.jobs.*.tasks[*].for_each_task.task.new_cluster.workload_type.clients compute.ClientsTypes ALL resources.jobs.*.tasks[*].for_each_task.task.new_cluster.workload_type.clients.jobs bool ALL @@ -1712,6 +1729,7 @@ resources.jobs.*.tasks[*].new_cluster.driver_instance_pool_id string ALL resources.jobs.*.tasks[*].new_cluster.driver_node_type_flexibility *compute.NodeTypeFlexibility ALL resources.jobs.*.tasks[*].new_cluster.driver_node_type_flexibility.alternate_node_type_ids []string ALL resources.jobs.*.tasks[*].new_cluster.driver_node_type_flexibility.alternate_node_type_ids[*] string ALL +resources.jobs.*.tasks[*].new_cluster.driver_node_type_flexibility.aws_context_id string ALL resources.jobs.*.tasks[*].new_cluster.driver_node_type_id string ALL resources.jobs.*.tasks[*].new_cluster.enable_elastic_disk bool ALL resources.jobs.*.tasks[*].new_cluster.enable_local_disk_encryption bool ALL @@ -1767,6 +1785,7 @@ resources.jobs.*.tasks[*].new_cluster.use_ml_runtime bool ALL resources.jobs.*.tasks[*].new_cluster.worker_node_type_flexibility *compute.NodeTypeFlexibility ALL resources.jobs.*.tasks[*].new_cluster.worker_node_type_flexibility.alternate_node_type_ids []string ALL resources.jobs.*.tasks[*].new_cluster.worker_node_type_flexibility.alternate_node_type_ids[*] string ALL +resources.jobs.*.tasks[*].new_cluster.worker_node_type_flexibility.aws_context_id string ALL resources.jobs.*.tasks[*].new_cluster.workload_type *compute.WorkloadType ALL resources.jobs.*.tasks[*].new_cluster.workload_type.clients compute.ClientsTypes ALL resources.jobs.*.tasks[*].new_cluster.workload_type.clients.jobs bool ALL @@ -1990,6 +2009,10 @@ resources.jobs.*.trigger_state.table.using_scalable_monitoring bool REMOTE resources.jobs.*.triggers []jobs.TriggerConfiguration ALL resources.jobs.*.triggers[*] jobs.TriggerConfiguration ALL resources.jobs.*.triggers[*].continuous *jobs.ContinuousTriggerConfiguration ALL +resources.jobs.*.triggers[*].continuous.maintenance_window *jobs.MaintenanceWindow ALL +resources.jobs.*.triggers[*].continuous.maintenance_window.day_of_week jobs.DayOfWeek ALL +resources.jobs.*.triggers[*].continuous.maintenance_window.start_hour int ALL +resources.jobs.*.triggers[*].continuous.maintenance_window.timezone_id string ALL resources.jobs.*.triggers[*].continuous.task_retry_mode jobs.TaskRetryMode ALL resources.jobs.*.triggers[*].file_arrival *jobs.FileArrivalTriggerConfiguration ALL resources.jobs.*.triggers[*].file_arrival.min_time_between_triggers_seconds int ALL @@ -2885,6 +2908,8 @@ resources.pipelines.*.ingestion_definition.objects[*].schema.connector_options.o resources.pipelines.*.ingestion_definition.objects[*].schema.connector_options.outlook_options.start_date string ALL resources.pipelines.*.ingestion_definition.objects[*].schema.connector_options.outlook_options.subject_filter []string ALL resources.pipelines.*.ingestion_definition.objects[*].schema.connector_options.outlook_options.subject_filter[*] string ALL +resources.pipelines.*.ingestion_definition.objects[*].schema.connector_options.rabbitmq_options *pipelines.RabbitmqOptions ALL +resources.pipelines.*.ingestion_definition.objects[*].schema.connector_options.rabbitmq_options.queue string ALL resources.pipelines.*.ingestion_definition.objects[*].schema.connector_options.reddit_ads_options *pipelines.RedditAdsOptions ALL resources.pipelines.*.ingestion_definition.objects[*].schema.connector_options.reddit_ads_options.custom_report_options *pipelines.RedditAdsOptionsRedditAdsCustomReportOptions ALL resources.pipelines.*.ingestion_definition.objects[*].schema.connector_options.reddit_ads_options.custom_report_options.breakdowns []string ALL @@ -3109,6 +3134,8 @@ resources.pipelines.*.ingestion_definition.objects[*].table.connector_options.ou resources.pipelines.*.ingestion_definition.objects[*].table.connector_options.outlook_options.start_date string ALL resources.pipelines.*.ingestion_definition.objects[*].table.connector_options.outlook_options.subject_filter []string ALL resources.pipelines.*.ingestion_definition.objects[*].table.connector_options.outlook_options.subject_filter[*] string ALL +resources.pipelines.*.ingestion_definition.objects[*].table.connector_options.rabbitmq_options *pipelines.RabbitmqOptions ALL +resources.pipelines.*.ingestion_definition.objects[*].table.connector_options.rabbitmq_options.queue string ALL resources.pipelines.*.ingestion_definition.objects[*].table.connector_options.reddit_ads_options *pipelines.RedditAdsOptions ALL resources.pipelines.*.ingestion_definition.objects[*].table.connector_options.reddit_ads_options.custom_report_options *pipelines.RedditAdsOptionsRedditAdsCustomReportOptions ALL resources.pipelines.*.ingestion_definition.objects[*].table.connector_options.reddit_ads_options.custom_report_options.breakdowns []string ALL @@ -3329,6 +3356,7 @@ resources.postgres_branches.*.replace_existing bool INPUT STATE resources.postgres_branches.*.source_branch string ALL resources.postgres_branches.*.source_branch_lsn string ALL resources.postgres_branches.*.source_branch_time *time.Time ALL +resources.postgres_branches.*.source_snapshot string ALL resources.postgres_branches.*.status *postgres.BranchStatus REMOTE resources.postgres_branches.*.status.branch_id string REMOTE resources.postgres_branches.*.status.current_state postgres.BranchStatusState REMOTE @@ -3342,6 +3370,7 @@ resources.postgres_branches.*.status.purge_time *time.Time REMOTE resources.postgres_branches.*.status.source_branch string REMOTE resources.postgres_branches.*.status.source_branch_lsn string REMOTE resources.postgres_branches.*.status.source_branch_time *time.Time REMOTE +resources.postgres_branches.*.status.source_snapshot string REMOTE resources.postgres_branches.*.status.state_change_time *time.Time REMOTE resources.postgres_branches.*.ttl *duration.Duration ALL resources.postgres_branches.*.uid string REMOTE diff --git a/acceptance/cmd/account/account-help/output.txt b/acceptance/cmd/account/account-help/output.txt index db1b4756a5f..7eb2484cb43 100644 --- a/acceptance/cmd/account/account-help/output.txt +++ b/acceptance/cmd/account/account-help/output.txt @@ -26,7 +26,7 @@ Settings network-connectivity These APIs provide configurations for the network connectivity of your workspaces for serverless compute resources. network-policies These APIs manage network policies for this account. settings Accounts Settings API allows users to manage settings at the account level. - settings-v2 *Public Preview* APIs to manage account level settings. + settings-v2 APIs to manage account level settings. workspace-network-configuration These APIs allow configuration of network settings for Databricks workspaces by selecting which network policy to associate with the workspace. Provisioning diff --git a/acceptance/help/output.txt b/acceptance/help/output.txt index 266e1227c48..31a95b392ef 100644 --- a/acceptance/help/output.txt +++ b/acceptance/help/output.txt @@ -101,7 +101,7 @@ Unity Catalog volumes Volumes are a Unity Catalog (UC) capability for accessing, storing, governing, organizing, and processing files. workspace-bindings A securable in Databricks can be configured as __OPEN__ or __ISOLATED__. -Delta Sharing +Open Sharing providers A data provider is an object representing the organization in the real world who shares the data. recipient-activation The Recipient Activation API is only applicable in the open sharing model where the recipient object has the authentication type of TOKEN. recipient-federation-policies *Public Preview* The Recipient Federation Policies APIs are only applicable in the open sharing model where the recipient object has the authentication type of OIDC_RECIPIENT, enabling data sharing from Databricks to non-Databricks recipients. @@ -115,7 +115,7 @@ Settings token-management Enables administrators to get all tokens and delete tokens for other users. tokens The Token API allows you to create, list, and revoke tokens that can be used to authenticate and access Databricks REST APIs. workspace-conf This API allows updating known workspace settings for advanced users. - workspace-settings-v2 *Public Preview* APIs to manage workspace level settings. + workspace-settings-v2 APIs to manage workspace level settings. OAuth service-principal-secrets-proxy These APIs enable administrators to manage service principal secrets at the workspace level. diff --git a/bundle/config/mutator/resourcemutator/apply_presets.go b/bundle/config/mutator/resourcemutator/apply_presets.go index f31866a6fc3..33c3bd9741b 100644 --- a/bundle/config/mutator/resourcemutator/apply_presets.go +++ b/bundle/config/mutator/resourcemutator/apply_presets.go @@ -103,6 +103,7 @@ func (m *applyPresets) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnos p.Development = true } if t.TriggerPauseStatus == config.Paused { + //nolint:staticcheck // SA1019: pipeline continuous is deprecated in the SDK but remains a supported bundle config field p.Continuous = false } diff --git a/bundle/config/mutator/resourcemutator/apply_target_mode_test.go b/bundle/config/mutator/resourcemutator/apply_target_mode_test.go index 35eed05cc53..08c76f8433d 100644 --- a/bundle/config/mutator/resourcemutator/apply_target_mode_test.go +++ b/bundle/config/mutator/resourcemutator/apply_target_mode_test.go @@ -352,7 +352,7 @@ func TestProcessTargetModeDevelopment(t *testing.T) { // Pipeline 1 assert.Equal(t, "[dev lennart] pipeline1", b.Config.Resources.Pipelines["pipeline1"].Name) - assert.False(t, b.Config.Resources.Pipelines["pipeline1"].Continuous) + assert.False(t, b.Config.Resources.Pipelines["pipeline1"].Continuous) //nolint:staticcheck // SA1019: pipeline continuous is deprecated in the SDK but remains a supported bundle config field assert.True(t, b.Config.Resources.Pipelines["pipeline1"].Development) // Experiment 1 diff --git a/bundle/direct/dresources/pipeline.go b/bundle/direct/dresources/pipeline.go index c4592bc0ea3..aa9aae7ee33 100644 --- a/bundle/direct/dresources/pipeline.go +++ b/bundle/direct/dresources/pipeline.go @@ -110,7 +110,7 @@ func makePipelineRemote(p *pipelines.GetPipelineResponse) *PipelineRemote { Channel: spec.Channel, Clusters: spec.Clusters, Configuration: spec.Configuration, - Continuous: spec.Continuous, + Continuous: spec.Continuous, //nolint:staticcheck // SA1019: pipeline continuous is deprecated in the SDK but remains a supported bundle config field Deployment: spec.Deployment, Development: spec.Development, DryRun: false, @@ -179,7 +179,7 @@ func (r *ResourcePipeline) DoUpdate(ctx context.Context, id string, config *Pipe Channel: config.Channel, Clusters: config.Clusters, Configuration: config.Configuration, - Continuous: config.Continuous, + Continuous: config.Continuous, //nolint:staticcheck // SA1019: pipeline continuous is deprecated in the SDK but remains a supported bundle config field Deployment: config.Deployment, Development: config.Development, Edition: config.Edition, diff --git a/bundle/direct/dresources/resources.generated.yml b/bundle/direct/dresources/resources.generated.yml index d2dfda855b6..264ba81eca1 100644 --- a/bundle/direct/dresources/resources.generated.yml +++ b/bundle/direct/dresources/resources.generated.yml @@ -261,6 +261,8 @@ resources: reason: spec:immutable - field: source_branch_time reason: spec:immutable + - field: source_snapshot + reason: spec:immutable ignore_remote_changes: - field: expire_time @@ -275,6 +277,8 @@ resources: reason: spec:input_only - field: source_branch_time reason: spec:input_only + - field: source_snapshot + reason: spec:input_only - field: ttl reason: spec:input_only diff --git a/bundle/internal/validation/generated/enum_fields.go b/bundle/internal/validation/generated/enum_fields.go index 5e62e921687..e65f7ea4348 100644 --- a/bundle/internal/validation/generated/enum_fields.go +++ b/bundle/internal/validation/generated/enum_fields.go @@ -76,6 +76,7 @@ var EnumFields = map[string][]string{ "resources.job_runs.*.performance_target": {"PERFORMANCE_OPTIMIZED", "STANDARD"}, + "resources.jobs.*.continuous.maintenance_window.day_of_week": {"FRIDAY", "MONDAY", "SATURDAY", "SUNDAY", "THURSDAY", "TUESDAY", "WEDNESDAY"}, "resources.jobs.*.continuous.pause_status": {"PAUSED", "UNPAUSED"}, "resources.jobs.*.continuous.task_retry_mode": {"NEVER", "ON_FAILURE"}, "resources.jobs.*.deployment.kind": {"BUNDLE", "SYSTEM_MANAGED"}, @@ -99,11 +100,11 @@ var EnumFields = map[string][]string{ "resources.jobs.*.schedule.pause_status": {"PAUSED", "UNPAUSED"}, "resources.jobs.*.schedule.sql_condition.trigger_mode": {"QUERY_RETURNS_ROWS", "RESULT_VALUE_CHANGES"}, "resources.jobs.*.tasks[*].ai_runtime_task.deployments[*].compute.accelerator_type": {"GPU_1xA10", "GPU_1xH100", "GPU_8xH100"}, - "resources.jobs.*.tasks[*].compute.hardware_accelerator": {"GPU_1xA10", "GPU_8xH100"}, + "resources.jobs.*.tasks[*].compute.hardware_accelerator": {"GPU_1xA10", "GPU_1xH100", "GPU_8xH100"}, "resources.jobs.*.tasks[*].condition_task.op": {"EQUAL_TO", "GREATER_THAN", "GREATER_THAN_OR_EQUAL", "LESS_THAN", "LESS_THAN_OR_EQUAL", "NOT_EQUAL"}, "resources.jobs.*.tasks[*].dbt_task.source": {"GIT", "WORKSPACE"}, "resources.jobs.*.tasks[*].for_each_task.task.ai_runtime_task.deployments[*].compute.accelerator_type": {"GPU_1xA10", "GPU_1xH100", "GPU_8xH100"}, - "resources.jobs.*.tasks[*].for_each_task.task.compute.hardware_accelerator": {"GPU_1xA10", "GPU_8xH100"}, + "resources.jobs.*.tasks[*].for_each_task.task.compute.hardware_accelerator": {"GPU_1xA10", "GPU_1xH100", "GPU_8xH100"}, "resources.jobs.*.tasks[*].for_each_task.task.condition_task.op": {"EQUAL_TO", "GREATER_THAN", "GREATER_THAN_OR_EQUAL", "LESS_THAN", "LESS_THAN_OR_EQUAL", "NOT_EQUAL"}, "resources.jobs.*.tasks[*].for_each_task.task.dbt_task.source": {"GIT", "WORKSPACE"}, "resources.jobs.*.tasks[*].for_each_task.task.gen_ai_compute_task.source": {"GIT", "WORKSPACE"}, @@ -149,6 +150,7 @@ var EnumFields = map[string][]string{ "resources.jobs.*.trigger.periodic.unit": {"DAYS", "HOURS", "MINUTES", "WEEKS"}, "resources.jobs.*.trigger.sql_condition.trigger_mode": {"QUERY_RETURNS_ROWS", "RESULT_VALUE_CHANGES"}, "resources.jobs.*.trigger.table_update.condition": {"ALL_UPDATED", "ANY_UPDATED"}, + "resources.jobs.*.triggers[*].continuous.maintenance_window.day_of_week": {"FRIDAY", "MONDAY", "SATURDAY", "SUNDAY", "THURSDAY", "TUESDAY", "WEDNESDAY"}, "resources.jobs.*.triggers[*].continuous.task_retry_mode": {"NEVER", "ON_FAILURE"}, "resources.jobs.*.triggers[*].model.condition": {"MODEL_ALIAS_SET", "MODEL_CREATED", "MODEL_VERSION_READY"}, "resources.jobs.*.triggers[*].pause_status": {"PAUSED", "UNPAUSED"}, @@ -223,7 +225,7 @@ var EnumFields = map[string][]string{ "resources.pipelines.*.ingestion_definition.objects[*].table.connector_options.tiktok_ads_options.data_level": {"AUCTION_AD", "AUCTION_ADGROUP", "AUCTION_ADVERTISER", "AUCTION_CAMPAIGN"}, "resources.pipelines.*.ingestion_definition.objects[*].table.connector_options.tiktok_ads_options.report_type": {"AUDIENCE", "BASIC", "BUSINESS_CENTER", "DSA", "GMV_MAX", "PLAYABLE_AD"}, "resources.pipelines.*.ingestion_definition.objects[*].table.table_configuration.scd_type": {"APPEND_ONLY", "SCD_TYPE_1", "SCD_TYPE_2"}, - "resources.pipelines.*.ingestion_definition.source_type": {"BIGQUERY", "CONFLUENCE", "DYNAMICS365", "FOREIGN_CATALOG", "GA4_RAW_DATA", "GOOGLE_DRIVE", "JIRA", "MANAGED_POSTGRESQL", "META_MARKETING", "MYSQL", "NETSUITE", "ORACLE", "POSTGRESQL", "SALESFORCE", "SERVICENOW", "SHAREPOINT", "SQLSERVER", "TERADATA", "WORKDAY_RAAS", "ZENDESK"}, + "resources.pipelines.*.ingestion_definition.source_type": {"BIGQUERY", "CONFLUENCE", "DYNAMICS365", "FOREIGN_CATALOG", "GA4_RAW_DATA", "GOOGLE_DRIVE", "JIRA", "MANAGED_POSTGRESQL", "META_MARKETING", "MYSQL", "NETSUITE", "ORACLE", "POSTGRESQL", "RABBITMQ", "SALESFORCE", "SERVICENOW", "SHAREPOINT", "SQLSERVER", "TERADATA", "WORKDAY_RAAS", "ZENDESK"}, "resources.pipelines.*.ingestion_definition.table_configuration.scd_type": {"APPEND_ONLY", "SCD_TYPE_1", "SCD_TYPE_2"}, "resources.pipelines.*.permissions[*].level": {"CAN_MANAGE", "CAN_RUN", "CAN_VIEW", "IS_OWNER"}, "resources.pipelines.*.restart_window.days_of_week[*]": {"FRIDAY", "MONDAY", "SATURDAY", "SUNDAY", "THURSDAY", "TUESDAY", "WEDNESDAY"}, diff --git a/bundle/internal/validation/generated/required_fields.go b/bundle/internal/validation/generated/required_fields.go index 617f5a65ecc..fcdd9b11ab9 100644 --- a/bundle/internal/validation/generated/required_fields.go +++ b/bundle/internal/validation/generated/required_fields.go @@ -80,6 +80,7 @@ var RequiredFields = map[string][]string{ "resources.job_runs.*": {"job_id"}, "resources.job_runs.*.queue": {"enabled"}, + "resources.jobs.*.continuous.maintenance_window": {"day_of_week", "start_hour", "timezone_id"}, "resources.jobs.*.deployment": {"kind"}, "resources.jobs.*.environments[*]": {"environment_key"}, "resources.jobs.*.git_source": {"git_provider", "git_url"}, @@ -189,6 +190,7 @@ var RequiredFields = map[string][]string{ "resources.jobs.*.trigger.periodic": {"interval", "unit"}, "resources.jobs.*.trigger.sql_condition": {"sql_query_id", "warehouse_id"}, "resources.jobs.*.trigger.table_update": {"table_names"}, + "resources.jobs.*.triggers[*].continuous.maintenance_window": {"day_of_week", "start_hour", "timezone_id"}, "resources.jobs.*.triggers[*].file_arrival": {"url"}, "resources.jobs.*.triggers[*].model": {"condition"}, "resources.jobs.*.triggers[*].periodic": {"interval", "unit"}, @@ -236,15 +238,17 @@ var RequiredFields = map[string][]string{ "resources.pipelines.*.ingestion_definition.full_refresh_window": {"start_hour"}, "resources.pipelines.*.ingestion_definition.objects[*].report": {"destination_catalog", "destination_schema", "source_url"}, "resources.pipelines.*.ingestion_definition.objects[*].report.table_configuration.auto_full_refresh_policy": {"enabled"}, - "resources.pipelines.*.ingestion_definition.objects[*].schema": {"destination_catalog", "destination_schema", "source_schema"}, + "resources.pipelines.*.ingestion_definition.objects[*].schema": {"destination_catalog", "destination_schema"}, "resources.pipelines.*.ingestion_definition.objects[*].schema.connector_options.google_ads_options": {"manager_account_id"}, "resources.pipelines.*.ingestion_definition.objects[*].schema.connector_options.google_ads_options.custom_report_options": {"resource"}, "resources.pipelines.*.ingestion_definition.objects[*].schema.connector_options.linkedin_ads_options.custom_report_options": {"finder"}, + "resources.pipelines.*.ingestion_definition.objects[*].schema.connector_options.rabbitmq_options": {"queue"}, "resources.pipelines.*.ingestion_definition.objects[*].schema.table_configuration.auto_full_refresh_policy": {"enabled"}, - "resources.pipelines.*.ingestion_definition.objects[*].table": {"destination_catalog", "destination_schema", "source_table"}, + "resources.pipelines.*.ingestion_definition.objects[*].table": {"destination_catalog", "destination_schema"}, "resources.pipelines.*.ingestion_definition.objects[*].table.connector_options.google_ads_options": {"manager_account_id"}, "resources.pipelines.*.ingestion_definition.objects[*].table.connector_options.google_ads_options.custom_report_options": {"resource"}, "resources.pipelines.*.ingestion_definition.objects[*].table.connector_options.linkedin_ads_options.custom_report_options": {"finder"}, + "resources.pipelines.*.ingestion_definition.objects[*].table.connector_options.rabbitmq_options": {"queue"}, "resources.pipelines.*.ingestion_definition.objects[*].table.table_configuration.auto_full_refresh_policy": {"enabled"}, "resources.pipelines.*.ingestion_definition.table_configuration.auto_full_refresh_policy": {"enabled"}, "resources.pipelines.*.libraries[*].maven": {"coordinates"}, diff --git a/bundle/schema/jsonschema.json b/bundle/schema/jsonschema.json index 37246ebdff4..5967696cb91 100644 --- a/bundle/schema/jsonschema.json +++ b/bundle/schema/jsonschema.json @@ -106,7 +106,7 @@ "$ref": "#/$defs/github.com/databricks/cli/bundle/config/resources.Lifecycle" }, "parameters": { - "description": "[Private Preview] Query parameters bound when executing the alert query, referenced in the\nquery text with `:name` syntax. Static values only.", + "description": "[Private Preview] A list of parameters to pass into the alert SQL query statement containing parameter markers. Static values only.\n\nReference a parameter in the query text as `:name`. Each parameter must have a unique, non-empty name.\nEach parameter consists of a name, a value, and optionally a type. To represent a NULL\nvalue, the `value` field may be omitted or set to `null` explicitly. If the `type` field\nis omitted, the value is interpreted as a string.\n\nIf the type is given, parameters will be checked for type correctness according\nto the given type. A value is correct if the provided string can be converted to\nthe requested type using the `cast` function. The exact semantics are described in\nthe section [`cast` function](https://docs.databricks.com/sql/language-manual/functions/cast.html) of the SQL language reference.", "$ref": "#/$defs/slice/github.com/databricks/databricks-sdk-go/service/sql.AlertStatementParameter", "x-databricks-launch-stage": "PRIVATE_PREVIEW", "doNotSuggest": true @@ -538,7 +538,7 @@ "$ref": "#/$defs/slice/string" }, "total_initial_remote_disk_size": { - "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Currently only supported for GCP HYPERDISK_BALANCED disks.", + "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Supported for GCP.", "$ref": "#/$defs/int" }, "use_ml_runtime": { @@ -1116,7 +1116,7 @@ "$ref": "#/$defs/string" }, "continuous": { - "description": "An optional continuous property for this job. The continuous property will ensure that there is always one run executing. Only one of `schedule` and `continuous` can be used.", + "description": "An optional continuous property for this job. The continuous property will ensure that there is always one run executing. Only one of `schedule` and `continuous` can be used.\n\nPipelines started by a continuous job also run continuously, regardless of their own pipeline mode setting.", "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.Continuous" }, "description": { @@ -1762,8 +1762,10 @@ "$ref": "#/$defs/map/string" }, "continuous": { - "description": "Whether the pipeline is continuous or triggered. This replaces `trigger`.", - "$ref": "#/$defs/bool" + "description": "Whether the pipeline is continuous or triggered. This replaces `trigger`.\n\nDeprecated: wrap the pipeline in a continuous job instead, which also lets you take advantage\nof job-level settings such as performance mode. When the pipeline is started by a continuous\njob, the job's setting takes precedence and this field is ignored.", + "$ref": "#/$defs/bool", + "deprecationMessage": "This field is deprecated", + "deprecated": true }, "development": { "description": "Whether the pipeline is in Development mode. Defaults to false.", @@ -1974,6 +1976,12 @@ "description": "[Beta] The point in time on the source branch from which this branch was created.", "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/common/types/time.Time" }, + "source_snapshot": { + "description": "[Private Preview] The snapshot this branch was created from. When set, the branch's data\ncomes from the snapshot rather than a source branch, so source_branch,\nsource_branch_lsn, and source_branch_time must be empty. The snapshot must\nbe AVAILABLE and belong to this branch's project.\nFormat: projects/{project_id}/snapshots/{snapshot_id}", + "$ref": "#/$defs/string", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + }, "ttl": { "description": "[Beta] Relative time-to-live duration. When set, the branch will expire at creation_time + ttl.\nMutually exclusive with `expire_time` and `no_expiry`. When updating, use `spec.expiration` in the update_mask.", "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/common/types/duration.Duration" @@ -5697,7 +5705,7 @@ "$ref": "#/$defs/slice/string" }, "total_initial_remote_disk_size": { - "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Currently only supported for GCP HYPERDISK_BALANCED disks.", + "description": "If set, what the total initial volume size (in GB) of the remote disks should be. Supported for GCP.", "$ref": "#/$defs/int" }, "use_ml_runtime": { @@ -6105,9 +6113,11 @@ "description": "HardwareAcceleratorType: The type of hardware accelerator to use for compute workloads.\nNOTE: This enum is referenced and is intended to be used by other Databricks services\nthat need to specify hardware accelerator requirements for AI compute workloads.", "enum": [ "GPU_1xA10", - "GPU_8xH100" + "GPU_8xH100", + "GPU_1xH100" ], "enumDescriptions": [ + "[Beta]", "[Beta]", "[Beta]" ] @@ -6436,6 +6446,10 @@ "alternate_node_type_ids": { "description": "A list of node type IDs to use as fallbacks when the primary node type is unavailable.", "$ref": "#/$defs/slice/string" + }, + "aws_context_id": { + "description": "The AWS Context ID for EC2 Fleet.\nWhen set (non-empty), the value is passed to AWS CreateFleet API to create the EC2 Fleet.", + "$ref": "#/$defs/string" } }, "additionalProperties": false @@ -7199,6 +7213,12 @@ "description": "[Public Preview] The alert_id is the canonical identifier of the alert.", "$ref": "#/$defs/string" }, + "parameters": { + "description": "[Private Preview] Per-run parameter overrides, keyed by parameter name, applied onto the alert's stored\nquery parameters before the query is executed. Only scalar values are supported. Values\nmay reference job parameters with `{{job.parameters.*}}`, which are resolved before the\ntask runs. An override whose key does not match a stored parameter fails the task run.\nLimited to 10000 characters when serialized as JSON; keys must be 1-100 characters and\ncontain only letters, digits, underscores, dashes, and periods.", + "$ref": "#/$defs/map/string", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + }, "subscribers": { "description": "[Public Preview] The subscribers receive alert evaluation result notifications after the alert task is completed.\nThe number of subscriptions is limited to 100.", "$ref": "#/$defs/slice/github.com/databricks/databricks-sdk-go/service/jobs.AlertTaskSubscriber" @@ -7470,6 +7490,12 @@ { "type": "object", "properties": { + "maintenance_window": { + "description": "[Private Preview] Defines when platform-initiated maintenance may run for this job. If unspecified, maintenance may run at any time.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.MaintenanceWindow", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + }, "pause_status": { "description": "Indicate whether the continuous execution of the job is paused or not. Defaults to UNPAUSED.", "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.PauseStatus" @@ -7493,6 +7519,12 @@ "type": "object", "description": "Continuous trigger. Stripped-down counterpart to `ContinuousSettings`: `pause_status` is owned by the enclosing\n`TriggerConfiguration` and intentionally omitted here.", "properties": { + "maintenance_window": { + "description": "[Private Preview] Defines when platform-initiated maintenance may run for this trigger. If unspecified,\nmaintenance may run at any time.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.MaintenanceWindow", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + }, "task_retry_mode": { "description": "[Beta] Whether the continuous job applies task-level retries. Defaults to NEVER.", "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.TaskRetryMode" @@ -7602,6 +7634,36 @@ } ] }, + "jobs.DayOfWeek": { + "oneOf": [ + { + "type": "string", + "description": "Days of week that can be referenced by Jobs scheduling settings.", + "enum": [ + "MONDAY", + "TUESDAY", + "WEDNESDAY", + "THURSDAY", + "FRIDAY", + "SATURDAY", + "SUNDAY" + ], + "enumDescriptions": [ + "[Private Preview]", + "[Private Preview]", + "[Private Preview]", + "[Private Preview]", + "[Private Preview]", + "[Private Preview]", + "[Private Preview]" + ] + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\._*\\p{L}+([-_]*[\\p{L}\\p{N}]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] + }, "jobs.DbtCloudTask": { "oneOf": [ { @@ -8356,6 +8418,44 @@ } ] }, + "jobs.MaintenanceWindow": { + "oneOf": [ + { + "type": "object", + "description": "A recurring weekly time window during which platform-initiated maintenance is\nallowed to run for a continuous job.", + "properties": { + "day_of_week": { + "description": "[Private Preview] The day of week on which maintenance is allowed to happen. This field is required.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/jobs.DayOfWeek", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + }, + "start_hour": { + "description": "[Private Preview] An integer between 0 and 23 denoting the start hour for the maintenance window in the 24-hour day.\nPlatform-initiated maintenance is triggered only within a one-hour window starting at this hour.\nThis field is required.", + "$ref": "#/$defs/int", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + }, + "timezone_id": { + "description": "[Private Preview] A Java timezone ID. The maintenance window is resolved with respect to this timezone. See [Java TimeZone](https://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html) for details. This field is required.", + "$ref": "#/$defs/string", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + } + }, + "additionalProperties": false, + "required": [ + "day_of_week", + "start_hour", + "timezone_id" + ] + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\._*\\p{L}+([-_]*[\\p{L}\\p{N}]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] + }, "jobs.ModelTriggerConfiguration": { "oneOf": [ { @@ -9676,7 +9776,7 @@ "oneOf": [ { "type": "object", - "description": "A single trigger attached to a job via `JobSettings.triggers`. Exactly one of the trigger-type fields\n(`periodic`, `schedule`, `continuous`, `file_arrival`, `table_update`, `model`) must be set; mutual exclusivity\nis enforced in the API handler rather than via `oneof` so that codegen, validation, and JSON serialization\nacross SDKs and Terraform behave consistently.", + "description": "A single trigger attached to a job via `JobSettings.triggers`. Exactly one of the trigger-type fields\n(`periodic`, `schedule`, `continuous`, `file_arrival`, `table_update`, `model`, `job_completion`) must be set;\nmutual exclusivity is enforced in the API handler rather than via `oneof` so that codegen, validation, and JSON\nserialization across SDKs and Terraform behave consistently.", "properties": { "continuous": { "description": "[Beta] Continuous trigger configuration.", @@ -10123,6 +10223,10 @@ "x-databricks-launch-stage": "PRIVATE_PREVIEW", "doNotSuggest": true }, + "rabbitmq_options": { + "description": "[Beta] RabbitMQ specific options for ingestion.\nPerformance tuning options (consumers_per_task, max_messages_per_fetch, etc.)\nare intentionally not exposed in the public API. The managed connector uses\nsensible defaults internally. These can be added later if user demand arises.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/pipelines.RabbitmqOptions" + }, "reddit_ads_options": { "description": "[Private Preview] Reddit Ads specific options for ingestion", "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/pipelines.RedditAdsOptions", @@ -10944,6 +11048,7 @@ "CONFLUENCE", "META_MARKETING", "ZENDESK", + "RABBITMQ", "FOREIGN_CATALOG" ], "enumDescriptions": [ @@ -10966,6 +11071,7 @@ "[Public Preview]", "[Beta]", "[Public Preview]", + "[Beta]", "[Private Preview]" ] }, @@ -11633,7 +11739,7 @@ "$ref": "#/$defs/string" }, "label": { - "description": "A label for the cluster specification, either `default` to configure the default cluster, or `maintenance` to configure the maintenance cluster. This field is optional. The default value is `default`.", + "description": "A label for the cluster specification, either `default` to configure the default cluster settings applied to both the update and maintenance clusters, `updates` to configure the update cluster, or `maintenance` to configure the maintenance cluster. This field is optional. The default value is `default`.", "$ref": "#/$defs/string" }, "node_type_id": { @@ -11833,7 +11939,7 @@ "$ref": "#/$defs/slice/string" }, "environment_version": { - "description": "[Beta] The environment version of the serverless Python environment used to execute\ncustomer Python code. Each environment version includes a specific Python\nversion and a curated set of pre-installed libraries with defined versions,\nproviding a stable and reproducible execution environment.\n\nDatabricks supports a three-year lifecycle for each environment version.\nFor available versions and their included packages, see\nhttps://docs.databricks.com/aws/en/release-notes/serverless/environment-version/\n\nThe value should be a string representing the environment version number, for example: `\"4\"`.", + "description": "[Public Preview] The environment version of the serverless Python environment used to execute\ncustomer Python code. Each environment version includes a specific Python\nversion and a curated set of pre-installed libraries with defined versions,\nproviding a stable and reproducible execution environment.\n\nDatabricks supports a three-year lifecycle for each environment version.\nFor available versions and their included packages, see\nhttps://docs.databricks.com/aws/en/release-notes/serverless/environment-version/\n\nThe value should be a string representing the environment version number, for example: `\"4\"`.", "$ref": "#/$defs/string" } }, @@ -11887,6 +11993,28 @@ } ] }, + "pipelines.RabbitmqOptions": { + "oneOf": [ + { + "type": "object", + "description": "RabbitMQ specific options for ingestion.\nPerformance tuning options (consumers_per_task, max_messages_per_fetch, etc.)\nare intentionally not exposed in the public API. The managed connector uses\nsensible defaults internally. These can be added later if user demand arises.", + "properties": { + "queue": { + "description": "[Beta] (Required) RabbitMQ queue name to consume from.", + "$ref": "#/$defs/string" + } + }, + "additionalProperties": false, + "required": [ + "queue" + ] + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\._*\\p{L}+([-_]*[\\p{L}\\p{N}]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] + }, "pipelines.RedditAdsOptions": { "oneOf": [ { @@ -12070,7 +12198,7 @@ "$ref": "#/$defs/string" }, "source_schema": { - "description": "[Public Preview] Schema name in the source database. Currently required; this field will become optional in\nan upcoming release, since some source types (for example streaming / message-bus connectors)\ndo not use it. When that change ships, this field's type in the generated SDKs and CLI will\nchange from required to optional (nullable); clients that assume it is always present should\nhandle its absence.", + "description": "[Public Preview] Schema name in the source database. Optional: some source types (for example streaming or\nmessage-bus connectors) do not use it, so it may be absent from a pipeline's definition.\nClients that assume it is always present should handle its absence.", "$ref": "#/$defs/string" }, "table_configuration": { @@ -12081,8 +12209,7 @@ "additionalProperties": false, "required": [ "destination_catalog", - "destination_schema", - "source_schema" + "destination_schema" ] }, { @@ -12250,7 +12377,7 @@ "$ref": "#/$defs/string" }, "source_table": { - "description": "[Public Preview] Table name in the source database. Currently required; this field will become optional in\nan upcoming release, since some source types (for example streaming / message-bus connectors)\ndo not use it. When that change ships, this field's type in the generated SDKs and CLI will\nchange from required to optional (nullable); clients that assume it is always present should\nhandle its absence.", + "description": "[Public Preview] Table name in the source database. Optional: some source types (for example streaming or\nmessage-bus connectors) do not use it, so it may be absent from a pipeline's definition.\nClients that assume it is always present should handle its absence.", "$ref": "#/$defs/string" }, "table_configuration": { @@ -12261,8 +12388,7 @@ "additionalProperties": false, "required": [ "destination_catalog", - "destination_schema", - "source_table" + "destination_schema" ] }, { @@ -14339,22 +14465,22 @@ "oneOf": [ { "type": "object", - "description": "Redash-owned copy of the internal StatementParameter for the external AlertV2 API.\nThe internal `ordinal` and `args` fields are intentionally omitted: the public API\nsupports only flat, named scalar parameters; complex types (ARRAY, MAP, STRUCT) are\nnot supported. This mirrors SEA's public StatementParameter schema, see:\ncmdexec/sql-exec-api/proto/sql_exec_api_service.proto:763-779", + "description": "A named parameter bound to the alert query. Only flat, named scalar parameters are\nsupported; complex types such as ARRAY, MAP, and STRUCT are not.", "properties": { "name": { - "description": "[Private Preview] The name of the parameter, referenced in the query as `:name`.", + "description": "[Private Preview] The name of the parameter. Reference it in the query text as `:name`. Required, must be\nnon-empty, and must be unique across the alert's parameters.", "$ref": "#/$defs/string", "x-databricks-launch-stage": "PRIVATE_PREVIEW", "doNotSuggest": true }, "type": { - "description": "[Private Preview] The SQL data type of the parameter, e.g. STRING, INT, or DATE. Defaults to STRING. This is a\nstring rather than an enum because scalar subtypes such as DECIMAL(10, 4) cannot be enumerated.\nComplex types such as ARRAY, MAP, and STRUCT are not supported.", + "description": "[Private Preview] The SQL data type of the parameter, for example `STRING`, `INT`, or `DECIMAL(10, 2)`. If no type is given\nthe type is assumed to be `STRING`. Complex types such as `ARRAY`, `MAP`, and `STRUCT` are not supported.", "$ref": "#/$defs/string", "x-databricks-launch-stage": "PRIVATE_PREVIEW", "doNotSuggest": true }, "value": { - "description": "[Private Preview] The bound value for the parameter, given as a string. If omitted, the value is interpreted as NULL.", + "description": "[Private Preview] The value bound to the parameter, represented as a string. If omitted, the value is interpreted as NULL.", "$ref": "#/$defs/string", "x-databricks-launch-stage": "PRIVATE_PREVIEW", "doNotSuggest": true diff --git a/bundle/terraform_dabs_map/generated.go b/bundle/terraform_dabs_map/generated.go index d0a783f35ac..fe60c642473 100644 --- a/bundle/terraform_dabs_map/generated.go +++ b/bundle/terraform_dabs_map/generated.go @@ -6,18 +6,20 @@ package terraform_dabs_map // alerts / databricks_alert_v2: 3 tf-only // apps / databricks_app: 6 dabs-only // apps / databricks_app: 1 tf-only +// clusters / databricks_cluster: 2 dabs-only // clusters / databricks_cluster: 26 tf-only // dashboards / databricks_dashboard: 2 tf-only // database_instances / databricks_database_instance: 1 tf-only // experiments / databricks_mlflow_experiment: 1 tf-only // jobs / databricks_job: 11 renames -// jobs / databricks_job: 7 dabs-only +// jobs / databricks_job: 25 dabs-only // jobs / databricks_job: 259 tf-only // model_serving_endpoints / databricks_model_serving: 2 tf-only // models / databricks_mlflow_model: 1 renames // pipelines / databricks_pipeline: 3 renames -// pipelines / databricks_pipeline: 6 dabs-only +// pipelines / databricks_pipeline: 10 dabs-only // pipelines / databricks_pipeline: 2 tf-only +// postgres_branches / databricks_postgres_branch: 1 dabs-only // postgres_branches / databricks_postgres_branch: 1 unwraps // postgres_catalogs / databricks_postgres_catalog: 1 unwraps // postgres_databases / databricks_postgres_database: 1 unwraps @@ -100,15 +102,46 @@ var DABsOnlyFields = map[string]FieldSet{ }, }, }, + "clusters": { + "driver_node_type_flexibility": { + "aws_context_id": {}, // clusters.*.driver_node_type_flexibility.aws_context_id + }, + "worker_node_type_flexibility": { + "aws_context_id": {}, // clusters.*.worker_node_type_flexibility.aws_context_id + }, + }, "jobs": { + "continuous": { + "maintenance_window": { + "day_of_week": {}, // jobs.*.continuous.maintenance_window.day_of_week + "start_hour": {}, // jobs.*.continuous.maintenance_window.start_hour + "timezone_id": {}, // jobs.*.continuous.maintenance_window.timezone_id + }, + }, "job_clusters": { "new_cluster": { "autotermination_minutes": {}, // jobs.*.job_clusters.new_cluster.autotermination_minutes + "driver_node_type_flexibility": { + "aws_context_id": {}, // jobs.*.job_clusters.new_cluster.driver_node_type_flexibility.aws_context_id + }, + "worker_node_type_flexibility": { + "aws_context_id": {}, // jobs.*.job_clusters.new_cluster.worker_node_type_flexibility.aws_context_id + }, }, }, "tasks": { + "alert_task": { + "parameters": { + "*": {}, // jobs.*.tasks.alert_task.parameters.* + }, + }, "for_each_task": { "task": { + "alert_task": { + "parameters": { + "*": {}, // jobs.*.tasks.for_each_task.task.alert_task.parameters.* + }, + }, "for_each_task": { "concurrency": {}, // jobs.*.tasks.for_each_task.task.for_each_task.concurrency "inputs": {}, // jobs.*.tasks.for_each_task.task.for_each_task.inputs @@ -116,11 +149,32 @@ var DABsOnlyFields = map[string]FieldSet{ }, "new_cluster": { "autotermination_minutes": {}, // jobs.*.tasks.for_each_task.task.new_cluster.autotermination_minutes + "driver_node_type_flexibility": { + "aws_context_id": {}, // jobs.*.tasks.for_each_task.task.new_cluster.driver_node_type_flexibility.aws_context_id + }, + "worker_node_type_flexibility": { + "aws_context_id": {}, // jobs.*.tasks.for_each_task.task.new_cluster.worker_node_type_flexibility.aws_context_id + }, }, }, }, "new_cluster": { "autotermination_minutes": {}, // jobs.*.tasks.new_cluster.autotermination_minutes + "driver_node_type_flexibility": { + "aws_context_id": {}, // jobs.*.tasks.new_cluster.driver_node_type_flexibility.aws_context_id + }, + "worker_node_type_flexibility": { + "aws_context_id": {}, // jobs.*.tasks.new_cluster.worker_node_type_flexibility.aws_context_id + }, + }, + }, + "triggers": { + "continuous": { + "maintenance_window": { + "day_of_week": {}, // jobs.*.triggers.continuous.maintenance_window.day_of_week + "start_hour": {}, // jobs.*.triggers.continuous.maintenance_window.start_hour + "timezone_id": {}, // jobs.*.triggers.continuous.maintenance_window.timezone_id + }, }, }, }, @@ -133,10 +187,31 @@ var DABsOnlyFields = map[string]FieldSet{ }, }, "dry_run": {}, + "ingestion_definition": { + "objects": { + "schema": { + "connector_options": { + "rabbitmq_options": { + "queue": {}, // pipelines.*.ingestion_definition.objects.schema.connector_options.rabbitmq_options.queue + }, + }, + }, + "table": { + "connector_options": { + "rabbitmq_options": { + "queue": {}, // pipelines.*.ingestion_definition.objects.table.connector_options.rabbitmq_options.queue + }, + }, + }, + }, + }, "parameters": { "*": {}, // pipelines.*.parameters.* }, }, + "postgres_branches": { + "source_snapshot": {}, + }, "schemas": { "custom_max_retention_hours": {}, }, diff --git a/cmd/account/iam-v2/iam-v2.go b/cmd/account/iam-v2/iam-v2.go index 26da2acb5b1..d926b7a1635 100644 --- a/cmd/account/iam-v2/iam-v2.go +++ b/cmd/account/iam-v2/iam-v2.go @@ -50,6 +50,9 @@ These APIs are used to manage identities and the workspace access of these cmd.AddCommand(newDeleteWorkspaceAssignment()) cmd.AddCommand(newDeleteWorkspaceAssignmentDetail()) cmd.AddCommand(newGetDirectGroupMember()) + cmd.AddCommand(newGetExternalGroup()) + cmd.AddCommand(newGetExternalServicePrincipal()) + cmd.AddCommand(newGetExternalUser()) cmd.AddCommand(newGetGroup()) cmd.AddCommand(newGetServicePrincipal()) cmd.AddCommand(newGetUser()) @@ -99,8 +102,10 @@ func newCreateDirectGroupMember() *cobra.Command { cmd.Flags().Var(&createDirectGroupMemberJson, "json", `either inline JSON string or @path/to/file.json with request body`) cmd.Use = "create-direct-group-member GROUP_ID PRINCIPAL_ID" - cmd.Short = `Create a direct group membership.` - cmd.Long = `Create a direct group membership. + cmd.Short = `*Beta* Create a direct group membership.` + cmd.Long = `This command is in Beta and may change without notice. + +Create a direct group membership. Creates a group membership (assigns a principal to a group). @@ -108,12 +113,9 @@ func newCreateDirectGroupMember() *cobra.Command { GROUP_ID: Required. Internal ID of the group in Databricks. PRINCIPAL_ID: Internal ID of the principal in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("json") { @@ -199,8 +201,10 @@ func newCreateGroup() *cobra.Command { cmd.Flags().StringVar(&createGroupReq.Group.GroupName, "group-name", createGroupReq.Group.GroupName, `Display name of the group.`) cmd.Use = "create-group" - cmd.Short = `Create a group in the account.` - cmd.Long = `Create a group in the account. + cmd.Short = `*Beta* Create a group in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Create a group in the account. Creates a local group in the Databricks account and returns the created group. A local group is one that is not synced from the customer's identity provider, @@ -212,12 +216,9 @@ func newCreateGroup() *cobra.Command { ResolveGroup; to read an existing external identity, use the ExternalGroup resource.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(0) @@ -283,8 +284,10 @@ func newCreateServicePrincipal() *cobra.Command { cmd.Flags().StringVar(&createServicePrincipalReq.ServicePrincipal.ExternalId, "external-id", createServicePrincipalReq.ServicePrincipal.ExternalId, `ExternalId of the service principal in the customer's IdP.`) cmd.Use = "create-service-principal DISPLAY_NAME ACCOUNT_SP_STATUS" - cmd.Short = `Create a service principal in the account.` - cmd.Long = `Create a service principal in the account. + cmd.Short = `*Beta* Create a service principal in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Create a service principal in the account. Creates a local service principal in the Databricks account and returns the created service principal. A local service principal is one that is not synced @@ -301,12 +304,9 @@ func newCreateServicePrincipal() *cobra.Command { ACCOUNT_SP_STATUS: The activity status of a service principal in a Databricks account. Supported values: [ACTIVE, INACTIVE]` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("json") { @@ -389,8 +389,10 @@ func newCreateUser() *cobra.Command { cmd.Flags().StringVar(&createUserReq.User.ExternalId, "external-id", createUserReq.User.ExternalId, `ExternalId of the user in the customer's IdP.`) cmd.Use = "create-user USERNAME FULL_NAME ACCOUNT_USER_STATUS" - cmd.Short = `Create a user in the account.` - cmd.Long = `Create a user in the account. + cmd.Short = `*Beta* Create a user in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Create a user in the account. Creates a local user in the Databricks account and returns the created user. A local user is one that is not synced from the customer's identity provider, @@ -408,12 +410,9 @@ func newCreateUser() *cobra.Command { ACCOUNT_USER_STATUS: The activity status of a user in a Databricks account. Supported values: [ACTIVE, INACTIVE]` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("json") { @@ -504,8 +503,10 @@ func newCreateWorkspaceAssignment() *cobra.Command { // TODO: array: entitlements cmd.Use = "create-workspace-assignment WORKSPACE_ID PRINCIPAL_ID" - cmd.Short = `Create a workspace assignment.` - cmd.Long = `Create a workspace assignment. + cmd.Short = `*Beta* Create a workspace assignment.` + cmd.Long = `This command is in Beta and may change without notice. + +Create a workspace assignment. Creates a workspace assignment for a principal. Entitlements are granted one at a time rather than atomically. If the request fails partway through, the @@ -518,12 +519,9 @@ func newCreateWorkspaceAssignment() *cobra.Command { created. PRINCIPAL_ID: The internal ID of the principal (user/sp/group) in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("json") { @@ -612,11 +610,7 @@ func newCreateWorkspaceAssignmentDetail() *cobra.Command { cmd.Short = `Create a workspace assignment detail.` cmd.Long = `Create a workspace assignment detail. - Creates a workspace assignment detail for a principal. Entitlements are - granted one at a time rather than atomically. If the request fails partway - through, the principal stays assigned to the workspace with only some of the - requested entitlements. Get the assignment detail afterwards to confirm which - entitlements were granted. + Creates a workspace assignment detail for a principal. Arguments: WORKSPACE_ID: Required. The workspace ID for which the workspace assignment detail is @@ -707,8 +701,10 @@ func newDeleteDirectGroupMember() *cobra.Command { var deleteDirectGroupMemberReq iamv2.DeleteDirectGroupMemberRequest cmd.Use = "delete-direct-group-member GROUP_ID PRINCIPAL_ID" - cmd.Short = `Delete a direct group membership.` - cmd.Long = `Delete a direct group membership. + cmd.Short = `*Beta* Delete a direct group membership.` + cmd.Long = `This command is in Beta and may change without notice. + +Delete a direct group membership. Deletes a group membership (unassigns a principal from a group). @@ -716,12 +712,9 @@ func newDeleteDirectGroupMember() *cobra.Command { GROUP_ID: Required. Internal ID of the group in Databricks. PRINCIPAL_ID: Required. Internal ID of the principal to be unassigned from the group.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(2) @@ -777,20 +770,19 @@ func newDeleteGroup() *cobra.Command { var deleteGroupReq iamv2.DeleteGroupRequest cmd.Use = "delete-group GROUP_ID" - cmd.Short = `Delete a group in the account.` - cmd.Long = `Delete a group in the account. + cmd.Short = `*Beta* Delete a group in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Delete a group in the account. Deletes a group from the Databricks account by its internal ID. Arguments: GROUP_ID: Required. Internal ID of the group in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -838,20 +830,19 @@ func newDeleteServicePrincipal() *cobra.Command { var deleteServicePrincipalReq iamv2.DeleteServicePrincipalRequest cmd.Use = "delete-service-principal SERVICE_PRINCIPAL_ID" - cmd.Short = `Delete a service principal in the account.` - cmd.Long = `Delete a service principal in the account. + cmd.Short = `*Beta* Delete a service principal in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Delete a service principal in the account. Deletes a service principal from the Databricks account by its internal ID. Arguments: SERVICE_PRINCIPAL_ID: Required. Internal ID of the service principal in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -899,20 +890,19 @@ func newDeleteUser() *cobra.Command { var deleteUserReq iamv2.DeleteUserRequest cmd.Use = "delete-user USER_ID" - cmd.Short = `Delete a user in the account.` - cmd.Long = `Delete a user in the account. + cmd.Short = `*Beta* Delete a user in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Delete a user in the account. Deletes a user from the Databricks account by its internal ID. Arguments: USER_ID: Required. Internal ID of the user in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -960,8 +950,10 @@ func newDeleteWorkspaceAssignment() *cobra.Command { var deleteWorkspaceAssignmentReq iamv2.DeleteWorkspaceAssignmentRequest cmd.Use = "delete-workspace-assignment WORKSPACE_ID PRINCIPAL_ID" - cmd.Short = `Delete a workspace assignment.` - cmd.Long = `Delete a workspace assignment. + cmd.Short = `*Beta* Delete a workspace assignment.` + cmd.Long = `This command is in Beta and may change without notice. + +Delete a workspace assignment. Deletes a workspace assignment for a principal, revoking all of its entitlements. Entitlements are revoked one at a time rather than atomically. @@ -973,12 +965,9 @@ func newDeleteWorkspaceAssignment() *cobra.Command { PRINCIPAL_ID: Required. ID of the principal in Databricks to delete workspace assignment for.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(2) @@ -1108,8 +1097,10 @@ func newGetDirectGroupMember() *cobra.Command { var getDirectGroupMemberReq iamv2.GetDirectGroupMemberRequest cmd.Use = "get-direct-group-member GROUP_ID PRINCIPAL_ID" - cmd.Short = `Get a direct group member.` - cmd.Long = `Get a direct group member. + cmd.Short = `*Beta* Get a direct group member.` + cmd.Long = `This command is in Beta and may change without notice. + +Get a direct group member. Gets a provisioned direct member of a group. @@ -1118,12 +1109,9 @@ func newGetDirectGroupMember() *cobra.Command { PRINCIPAL_ID: Required. Internal ID of the principal belonging to the group in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(2) @@ -1165,6 +1153,200 @@ func newGetDirectGroupMember() *cobra.Command { return cmd } +// start get-external-group command + +// Slice with functions to override default command behavior. +// Functions can be added from the `init()` function in manually curated files in this directory. +var getExternalGroupOverrides []func( + *cobra.Command, + *iamv2.GetExternalGroupRequest, +) + +func newGetExternalGroup() *cobra.Command { + cmd := &cobra.Command{} + + var getExternalGroupReq iamv2.GetExternalGroupRequest + + cmd.Use = "get-external-group NAME" + cmd.Short = `*Beta* Get an external group in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Get an external group in the account. + + Retrieves an external group with the given external ID from the customer's + IdP. If the group does not exist, it will be created in the account. If the + customer is not onboarded onto Automatic Identity Management (AIM), this will + return an error. + + Arguments: + NAME: Required. The resource name of the external group. Format: + accounts/{account_id}/external-groups/{external_group_id}` + + cmd.Annotations = make(map[string]string) + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" + + cmd.Args = func(cmd *cobra.Command, args []string) error { + check := root.ExactArgs(1) + return check(cmd, args) + } + + cmd.PreRunE = root.MustAccountClient + cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { + ctx := cmd.Context() + a := cmdctx.AccountClient(ctx) + + getExternalGroupReq.Name = args[0] + + response, err := a.IamV2.GetExternalGroup(ctx, getExternalGroupReq) + if err != nil { + return err + } + + return cmdio.Render(ctx, response) + } + + // Disable completions since they are not applicable. + // Can be overridden by manual implementation in `override.go`. + cmd.ValidArgsFunction = cobra.NoFileCompletions + + // Apply optional overrides to this command. + for _, fn := range getExternalGroupOverrides { + fn(cmd, &getExternalGroupReq) + } + + return cmd +} + +// start get-external-service-principal command + +// Slice with functions to override default command behavior. +// Functions can be added from the `init()` function in manually curated files in this directory. +var getExternalServicePrincipalOverrides []func( + *cobra.Command, + *iamv2.GetExternalServicePrincipalRequest, +) + +func newGetExternalServicePrincipal() *cobra.Command { + cmd := &cobra.Command{} + + var getExternalServicePrincipalReq iamv2.GetExternalServicePrincipalRequest + + cmd.Use = "get-external-service-principal NAME" + cmd.Short = `*Beta* Get an external service principal in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Get an external service principal in the account. + + Retrieves an external service principal with the given external ID from the + customer's IdP. If the service principal does not exist, it will be created. + If the customer is not onboarded onto Automatic Identity Management (AIM), + this will return an error. + + Arguments: + NAME: Required. The resource name of the external service principal. Format: + accounts/{account_id}/external-service-principals/{external_service_principal_id}` + + cmd.Annotations = make(map[string]string) + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" + + cmd.Args = func(cmd *cobra.Command, args []string) error { + check := root.ExactArgs(1) + return check(cmd, args) + } + + cmd.PreRunE = root.MustAccountClient + cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { + ctx := cmd.Context() + a := cmdctx.AccountClient(ctx) + + getExternalServicePrincipalReq.Name = args[0] + + response, err := a.IamV2.GetExternalServicePrincipal(ctx, getExternalServicePrincipalReq) + if err != nil { + return err + } + + return cmdio.Render(ctx, response) + } + + // Disable completions since they are not applicable. + // Can be overridden by manual implementation in `override.go`. + cmd.ValidArgsFunction = cobra.NoFileCompletions + + // Apply optional overrides to this command. + for _, fn := range getExternalServicePrincipalOverrides { + fn(cmd, &getExternalServicePrincipalReq) + } + + return cmd +} + +// start get-external-user command + +// Slice with functions to override default command behavior. +// Functions can be added from the `init()` function in manually curated files in this directory. +var getExternalUserOverrides []func( + *cobra.Command, + *iamv2.GetExternalUserRequest, +) + +func newGetExternalUser() *cobra.Command { + cmd := &cobra.Command{} + + var getExternalUserReq iamv2.GetExternalUserRequest + + cmd.Use = "get-external-user NAME" + cmd.Short = `*Beta* Get an external user in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Get an external user in the account. + + Retrieves an external user with the given external ID from the customer's IdP. + If the user does not exist, it will be created. If the customer is not + onboarded onto Automatic Identity Management (AIM), this will return an error. + + Arguments: + NAME: Required. The resource name of the external user. Format: + accounts/{account_id}/external-users/{external_user_id}` + + cmd.Annotations = make(map[string]string) + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" + + cmd.Args = func(cmd *cobra.Command, args []string) error { + check := root.ExactArgs(1) + return check(cmd, args) + } + + cmd.PreRunE = root.MustAccountClient + cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { + ctx := cmd.Context() + a := cmdctx.AccountClient(ctx) + + getExternalUserReq.Name = args[0] + + response, err := a.IamV2.GetExternalUser(ctx, getExternalUserReq) + if err != nil { + return err + } + + return cmdio.Render(ctx, response) + } + + // Disable completions since they are not applicable. + // Can be overridden by manual implementation in `override.go`. + cmd.ValidArgsFunction = cobra.NoFileCompletions + + // Apply optional overrides to this command. + for _, fn := range getExternalUserOverrides { + fn(cmd, &getExternalUserReq) + } + + return cmd +} + // start get-group command // Slice with functions to override default command behavior. @@ -1180,20 +1362,19 @@ func newGetGroup() *cobra.Command { var getGroupReq iamv2.GetGroupRequest cmd.Use = "get-group GROUP_ID" - cmd.Short = `Get a group in the account.` - cmd.Long = `Get a group in the account. + cmd.Short = `*Beta* Get a group in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Get a group in the account. Fetches a group from the Databricks account by its internal ID. Arguments: GROUP_ID: Required. Internal ID of the group in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -1242,20 +1423,19 @@ func newGetServicePrincipal() *cobra.Command { var getServicePrincipalReq iamv2.GetServicePrincipalRequest cmd.Use = "get-service-principal SERVICE_PRINCIPAL_ID" - cmd.Short = `Get a service principal in the account.` - cmd.Long = `Get a service principal in the account. + cmd.Short = `*Beta* Get a service principal in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Get a service principal in the account. Fetches a service principal from the Databricks account by its internal ID. Arguments: SERVICE_PRINCIPAL_ID: Required. Internal ID of the service principal in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -1304,20 +1484,19 @@ func newGetUser() *cobra.Command { var getUserReq iamv2.GetUserRequest cmd.Use = "get-user USER_ID" - cmd.Short = `Get a user in the account.` - cmd.Long = `Get a user in the account. + cmd.Short = `*Beta* Get a user in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Get a user in the account. Fetches a user from the Databricks account by its internal ID. Arguments: USER_ID: Required. Internal ID of the user in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -1445,8 +1624,10 @@ func newGetWorkspaceAssignment() *cobra.Command { var getWorkspaceAssignmentReq iamv2.GetWorkspaceAssignmentRequest cmd.Use = "get-workspace-assignment WORKSPACE_ID PRINCIPAL_ID" - cmd.Short = `Get a workspace assignment for a principal.` - cmd.Long = `Get a workspace assignment for a principal. + cmd.Short = `*Beta* Get a workspace assignment for a principal.` + cmd.Long = `This command is in Beta and may change without notice. + +Get a workspace assignment for a principal. Returns the assignment for a principal in a workspace. @@ -1455,12 +1636,9 @@ func newGetWorkspaceAssignment() *cobra.Command { PRINCIPAL_ID: Required. The internal ID of the principal (user/sp/group) for which the assignment is being requested.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(2) @@ -1603,8 +1781,10 @@ func newListDirectGroupMembers() *cobra.Command { cmd.Flags().Lookup("page-token").Hidden = true cmd.Use = "list-direct-group-members GROUP_ID" - cmd.Short = `List direct group members.` - cmd.Long = `List direct group members. + cmd.Short = `*Beta* List direct group members.` + cmd.Long = `This command is in Beta and may change without notice. + +List direct group members. Lists provisioned direct members of a group with their membership source (internal or from identity provider). @@ -1613,12 +1793,9 @@ func newListDirectGroupMembers() *cobra.Command { GROUP_ID: Required. Internal ID of the group in Databricks whose direct members are being listed.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -1687,18 +1864,17 @@ func newListGroups() *cobra.Command { cmd.Flags().Lookup("page-token").Hidden = true cmd.Use = "list-groups" - cmd.Short = `List groups in the account.` - cmd.Long = `List groups in the account. + cmd.Short = `*Beta* List groups in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +List groups in the account. Lists the groups in the Databricks account, returning one page per call. Supports filtering by group name or external ID.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(0) @@ -1762,18 +1938,17 @@ func newListServicePrincipals() *cobra.Command { cmd.Flags().Lookup("page-token").Hidden = true cmd.Use = "list-service-principals" - cmd.Short = `List service principals in the account.` - cmd.Long = `List service principals in the account. + cmd.Short = `*Beta* List service principals in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +List service principals in the account. Lists the service principals in the Databricks account, returning one page per call. Supports filtering by application ID or external ID.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(0) @@ -1826,8 +2001,10 @@ func newListTransitiveParentGroups() *cobra.Command { cmd.Flags().StringVar(&listTransitiveParentGroupsReq.PageToken, "page-token", listTransitiveParentGroupsReq.PageToken, `A page token, received from a previous ListTransitiveParentGroups call.`) cmd.Use = "list-transitive-parent-groups PRINCIPAL_ID" - cmd.Short = `List all transitive parent groups of a principal.` - cmd.Long = `List all transitive parent groups of a principal. + cmd.Short = `*Beta* List all transitive parent groups of a principal.` + cmd.Long = `This command is in Beta and may change without notice. + +List all transitive parent groups of a principal. Lists all transitive parent groups of a principal. @@ -1835,12 +2012,9 @@ func newListTransitiveParentGroups() *cobra.Command { PRINCIPAL_ID: Required. Internal ID of the principal in Databricks whose transitive parent groups are being listed.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -1906,18 +2080,17 @@ func newListUsers() *cobra.Command { cmd.Flags().Lookup("page-token").Hidden = true cmd.Use = "list-users" - cmd.Short = `List users in the account.` - cmd.Long = `List users in the account. + cmd.Short = `*Beta* List users in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +List users in the account. Lists the users in the Databricks account, returning one page per call. Supports filtering by username or external ID.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(0) @@ -2065,8 +2238,10 @@ func newListWorkspaceAssignments() *cobra.Command { cmd.Flags().Lookup("page-token").Hidden = true cmd.Use = "list-workspace-assignments WORKSPACE_ID" - cmd.Short = `List workspace assignments for a workspace.` - cmd.Long = `List workspace assignments for a workspace. + cmd.Short = `*Beta* List workspace assignments for a workspace.` + cmd.Long = `This command is in Beta and may change without notice. + +List workspace assignments for a workspace. Lists workspace assignments for a workspace. The response omits the per-principal entitlement fields (entitlements and @@ -2077,12 +2252,9 @@ func newListWorkspaceAssignments() *cobra.Command { WORKSPACE_ID: Required. The workspace ID for which the workspace assignments are being fetched.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -2407,8 +2579,10 @@ func newUpdateGroup() *cobra.Command { cmd.Flags().StringVar(&updateGroupReq.Group.GroupName, "group-name", updateGroupReq.Group.GroupName, `Display name of the group.`) cmd.Use = "update-group GROUP_ID UPDATE_MASK" - cmd.Short = `Update a group in the account.` - cmd.Long = `Update a group in the account. + cmd.Short = `*Beta* Update a group in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Update a group in the account. Updates an existing group in the Databricks account. Only the fields named in the update mask are modified. Returns the updated Group resource. @@ -2421,12 +2595,9 @@ func newUpdateGroup() *cobra.Command { GROUP_ID: Required. Internal ID of the group in Databricks. UPDATE_MASK: Optional. The list of fields to update.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(2) @@ -2494,8 +2665,10 @@ func newUpdateServicePrincipal() *cobra.Command { cmd.Flags().StringVar(&updateServicePrincipalReq.ServicePrincipal.ExternalId, "external-id", updateServicePrincipalReq.ServicePrincipal.ExternalId, `ExternalId of the service principal in the customer's IdP.`) cmd.Use = "update-service-principal SERVICE_PRINCIPAL_ID UPDATE_MASK DISPLAY_NAME ACCOUNT_SP_STATUS" - cmd.Short = `Update a service principal in the account.` - cmd.Long = `Update a service principal in the account. + cmd.Short = `*Beta* Update a service principal in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Update a service principal in the account. Updates an existing service principal in the Databricks account. Only the fields named in the update mask are modified. Returns the updated @@ -2512,12 +2685,9 @@ func newUpdateServicePrincipal() *cobra.Command { ACCOUNT_SP_STATUS: The activity status of a service principal in a Databricks account. Supported values: [ACTIVE, INACTIVE]` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("json") { @@ -2602,8 +2772,10 @@ func newUpdateUser() *cobra.Command { cmd.Flags().StringVar(&updateUserReq.User.ExternalId, "external-id", updateUserReq.User.ExternalId, `ExternalId of the user in the customer's IdP.`) cmd.Use = "update-user USER_ID UPDATE_MASK USERNAME FULL_NAME ACCOUNT_USER_STATUS" - cmd.Short = `Update a user in the account.` - cmd.Long = `Update a user in the account. + cmd.Short = `*Beta* Update a user in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Update a user in the account. Updates an existing user in the Databricks account and returns the updated user. Only the fields named in the update mask are modified. The updatable @@ -2621,12 +2793,9 @@ func newUpdateUser() *cobra.Command { ACCOUNT_USER_STATUS: The activity status of a user in a Databricks account. Supported values: [ACTIVE, INACTIVE]` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("json") { @@ -2719,8 +2888,10 @@ func newUpdateWorkspaceAssignment() *cobra.Command { // TODO: array: entitlements cmd.Use = "update-workspace-assignment WORKSPACE_ID PRINCIPAL_ID UPDATE_MASK PRINCIPAL_ID" - cmd.Short = `Update a workspace assignment.` - cmd.Long = `Update a workspace assignment. + cmd.Short = `*Beta* Update a workspace assignment.` + cmd.Long = `This command is in Beta and may change without notice. + +Update a workspace assignment. Updates the entitlements of a directly assigned principal in a workspace. Changes are applied one at a time rather than atomically. If the request fails @@ -2734,12 +2905,9 @@ func newUpdateWorkspaceAssignment() *cobra.Command { UPDATE_MASK: Required. The list of fields to update. PRINCIPAL_ID: The internal ID of the principal (user/sp/group) in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("json") { diff --git a/cmd/account/settings-v2/settings-v2.go b/cmd/account/settings-v2/settings-v2.go index 91d655c2ef1..11b27a5802b 100644 --- a/cmd/account/settings-v2/settings-v2.go +++ b/cmd/account/settings-v2/settings-v2.go @@ -19,18 +19,16 @@ var cmdOverrides []func(*cobra.Command) func New() *cobra.Command { cmd := &cobra.Command{ - Use: "settings-v2", - Short: `*Public Preview* APIs to manage account level settings.`, - Long: `This command is in Public Preview and may change without notice. - -APIs to manage account level settings`, + Use: "settings-v2", + Short: `APIs to manage account level settings.`, + Long: `APIs to manage account level settings`, GroupID: "settings", RunE: root.ReportUnknownSubcommand, } cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PUBLIC_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Public Preview" + cmd.Annotations["launch_stage"] = "GA" + cmd.Annotations["launch_stage_display"] = "GA" // Add methods cmd.AddCommand(newGetPublicAccountSetting()) @@ -63,18 +61,16 @@ func newGetPublicAccountSetting() *cobra.Command { var getPublicAccountSettingReq settingsv2.GetPublicAccountSettingRequest cmd.Use = "get-public-account-setting NAME" - cmd.Short = `*Public Preview* Get an account setting.` - cmd.Long = `This command is in Public Preview and may change without notice. - -Get an account setting. + cmd.Short = `Get an account setting.` + cmd.Long = `Get an account setting. Get a setting value at account level. See :method:settingsv2/listaccountsettingsmetadata for list of setting available via public APIs at account level.` cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PUBLIC_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Public Preview" + cmd.Annotations["launch_stage"] = "GA" + cmd.Annotations["launch_stage_display"] = "GA" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -202,18 +198,16 @@ func newListAccountSettingsMetadata() *cobra.Command { cmd.Flags().Lookup("page-token").Hidden = true cmd.Use = "list-account-settings-metadata" - cmd.Short = `*Public Preview* List valid setting keys and their metadata.` - cmd.Long = `This command is in Public Preview and may change without notice. - -List valid setting keys and their metadata. + cmd.Short = `List valid setting keys and their metadata.` + cmd.Long = `List valid setting keys and their metadata. List valid setting keys and metadata. These settings are available to be referenced via GET :method:settingsv2/getpublicaccountsetting and PATCH :method:settingsv2/patchpublicaccountsetting APIs` cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PUBLIC_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Public Preview" + cmd.Annotations["launch_stage"] = "GA" + cmd.Annotations["launch_stage_display"] = "GA" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(0) @@ -372,10 +366,8 @@ func newPatchPublicAccountSetting() *cobra.Command { // TODO: complex arg: string_val cmd.Use = "patch-public-account-setting NAME" - cmd.Short = `*Public Preview* Update an account setting.` - cmd.Long = `This command is in Public Preview and may change without notice. - -Update an account setting. + cmd.Short = `Update an account setting.` + cmd.Long = `Update an account setting. Patch a setting value at account level. See :method:settingsv2/listaccountsettingsmetadata for list of setting available @@ -386,8 +378,8 @@ Update an account setting. Note: Page refresh is required for changes to take effect in UI.` cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PUBLIC_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Public Preview" + cmd.Annotations["launch_stage"] = "GA" + cmd.Annotations["launch_stage_display"] = "GA" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) diff --git a/cmd/workspace/alerts-v2/alerts-v2.go b/cmd/workspace/alerts-v2/alerts-v2.go index 48fe68451c0..8379b126d5f 100644 --- a/cmd/workspace/alerts-v2/alerts-v2.go +++ b/cmd/workspace/alerts-v2/alerts-v2.go @@ -404,7 +404,7 @@ func newUpdateAlert() *cobra.Command { Update alert Arguments: - ID: UUID identifying the alert. + ID: The canonical identifier of the alert to retrieve information about. UPDATE_MASK: The field mask must be a single string, with multiple fields separated by commas (no spaces). The field path is relative to the resource object, using a dot (.) to navigate sub-fields (e.g., author.given_name). diff --git a/cmd/workspace/apps/apps.go b/cmd/workspace/apps/apps.go index 7d17583663c..173574b8e69 100644 --- a/cmd/workspace/apps/apps.go +++ b/cmd/workspace/apps/apps.go @@ -226,6 +226,7 @@ func newCreateSpace() *cobra.Command { cmd.Flags().Var(&createSpaceJson, "json", `either inline JSON string or @path/to/file.json with request body`) + cmd.Flags().StringVar(&createSpaceReq.Space.AssumeGroupId, "assume-group-id", createSpaceReq.Space.AssumeGroupId, `The group whose permissions users assume via Role Authorization for apps in this space.`) cmd.Flags().StringVar(&createSpaceReq.Space.Description, "description", createSpaceReq.Space.Description, `The description of the app space.`) // TODO: array: effective_user_api_scopes // TODO: array: resources @@ -1951,6 +1952,7 @@ func newUpdateSpace() *cobra.Command { cmd.Flags().Var(&updateSpaceJson, "json", `either inline JSON string or @path/to/file.json with request body`) + cmd.Flags().StringVar(&updateSpaceReq.Space.AssumeGroupId, "assume-group-id", updateSpaceReq.Space.AssumeGroupId, `The group whose permissions users assume via Role Authorization for apps in this space.`) cmd.Flags().StringVar(&updateSpaceReq.Space.Description, "description", updateSpaceReq.Space.Description, `The description of the app space.`) // TODO: array: effective_user_api_scopes // TODO: array: resources diff --git a/cmd/workspace/bundle-deployments/bundle-deployments.go b/cmd/workspace/bundle-deployments/bundle-deployments.go index 5af8fbfdd35..e93a69099e6 100644 --- a/cmd/workspace/bundle-deployments/bundle-deployments.go +++ b/cmd/workspace/bundle-deployments/bundle-deployments.go @@ -48,6 +48,7 @@ func New() *cobra.Command { cmd.AddCommand(newListOperations()) cmd.AddCommand(newListResources()) cmd.AddCommand(newListVersions()) + cmd.AddCommand(newUpdateDeployment()) cmd.AddCommand(newUpdateOperation()) // Apply optional overrides to this command. @@ -176,8 +177,11 @@ func newCreateDeployment() *cobra.Command { cmd.Flags().Var(&createDeploymentJson, "json", `either inline JSON string or @path/to/file.json with request body`) + cmd.Flags().Var(&createDeploymentReq.Deployment.DeploymentMode, "deployment-mode", `Bundle target deployment mode (development or production). Supported values: [DEPLOYMENT_MODE_DEVELOPMENT, DEPLOYMENT_MODE_PRODUCTION]`) + cmd.Flags().StringVar(&createDeploymentReq.Deployment.DisplayName, "display-name", createDeploymentReq.Deployment.DisplayName, `Human-readable name for the deployment, up to 256 characters.`) // TODO: complex arg: git_info cmd.Flags().StringVar(&createDeploymentReq.Deployment.InitialParentPath, "initial-parent-path", createDeploymentReq.Deployment.InitialParentPath, `The workspace path of the existing folder where the deployment is initially created.`) + cmd.Flags().StringVar(&createDeploymentReq.Deployment.TargetName, "target-name", createDeploymentReq.Deployment.TargetName, `The bundle target name associated with this deployment.`) // TODO: complex arg: workspace_info cmd.Use = "create-deployment" @@ -254,6 +258,7 @@ func newCreateVersion() *cobra.Command { cmd.Flags().Var(&createVersionReq.Version.DeploymentMode, "deployment-mode", `Bundle target deployment mode (development or production), captured at the time of this version. Supported values: [DEPLOYMENT_MODE_DEVELOPMENT, DEPLOYMENT_MODE_PRODUCTION]`) cmd.Flags().StringVar(&createVersionReq.Version.DisplayName, "display-name", createVersionReq.Version.DisplayName, `Display name for the deployment, captured at the time of this version.`) // TODO: complex arg: git_info + // TODO: array: operations cmd.Flags().StringVar(&createVersionReq.Version.PreviousVersionId, "previous-version-id", createVersionReq.Version.PreviousVersionId, `The version_id this version was created on top of — the deployment's most recent version at creation time.`) cmd.Flags().StringVar(&createVersionReq.Version.TargetName, "target-name", createVersionReq.Version.TargetName, `Target name of the deployment, captured at the time of this version.`) // TODO: complex arg: workspace_info @@ -1018,6 +1023,83 @@ func newListVersions() *cobra.Command { return cmd } +// start update-deployment command + +// Slice with functions to override default command behavior. +// Functions can be added from the `init()` function in manually curated files in this directory. +var updateDeploymentOverrides []func( + *cobra.Command, + *bundledeployments.UpdateDeploymentRequest, +) + +func newUpdateDeployment() *cobra.Command { + cmd := &cobra.Command{} + + var updateDeploymentReq bundledeployments.UpdateDeploymentRequest + updateDeploymentReq.Deployment = bundledeployments.Deployment{} + var updateDeploymentJson flags.JsonFlag + + cmd.Flags().Var(&updateDeploymentJson, "json", `either inline JSON string or @path/to/file.json with request body`) + + cmd.Use = "update-deployment NAME" + cmd.Short = `Update a deployment.` + cmd.Long = `Update a deployment. + + Updates a deployment. + + Arguments: + NAME: Resource name of the deployment. Format: deployments/{deployment_id}` + + cmd.Annotations = make(map[string]string) + cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" + cmd.Annotations["launch_stage_display"] = "Private Preview" + + cmd.Args = func(cmd *cobra.Command, args []string) error { + check := root.ExactArgs(1) + return check(cmd, args) + } + + cmd.PreRunE = root.MustWorkspaceClient + cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { + ctx := cmd.Context() + w := cmdctx.WorkspaceClient(ctx) + + if cmd.Flags().Changed("json") { + diags := updateDeploymentJson.Unmarshal(&updateDeploymentReq.Deployment) + if diags.HasError() { + return diags.Error() + } + if len(diags) > 0 { + err := cmdio.RenderDiagnostics(ctx, diags) + if err != nil { + return err + } + } + } else { + return errors.New("please provide command input in JSON format by specifying the --json flag") + } + updateDeploymentReq.Name = args[0] + + response, err := w.BundleDeployments.UpdateDeployment(ctx, updateDeploymentReq) + if err != nil { + return err + } + + return cmdio.Render(ctx, response) + } + + // Disable completions since they are not applicable. + // Can be overridden by manual implementation in `override.go`. + cmd.ValidArgsFunction = cobra.NoFileCompletions + + // Apply optional overrides to this command. + for _, fn := range updateDeploymentOverrides { + fn(cmd, &updateDeploymentReq) + } + + return cmd +} + // start update-operation command // Slice with functions to override default command behavior. diff --git a/cmd/workspace/feature-engineering/feature-engineering.go b/cmd/workspace/feature-engineering/feature-engineering.go index 4dca56a0c8c..3602959289b 100644 --- a/cmd/workspace/feature-engineering/feature-engineering.go +++ b/cmd/workspace/feature-engineering/feature-engineering.go @@ -86,10 +86,7 @@ func newCreateFeature() *cobra.Command { cmd.Flags().StringVar(&createFeatureReq.Feature.Description, "description", createFeatureReq.Feature.Description, `The description of the feature.`) // TODO: array: entities - cmd.Flags().StringVar(&createFeatureReq.Feature.FilterCondition, "filter-condition", createFeatureReq.Feature.FilterCondition, `Deprecated: Use DeltaTableSource.filter_condition or KafkaSource.filter_condition instead.`) - // TODO: array: inputs // TODO: complex arg: lineage_context - // TODO: complex arg: time_window // TODO: complex arg: timeseries_column cmd.Use = "create-feature FULL_NAME SOURCE FUNCTION" @@ -308,7 +305,6 @@ func newCreateMaterializedFeature() *cobra.Command { cmd.Flags().Var(&createMaterializedFeatureJson, "json", `either inline JSON string or @path/to/file.json with request body`) - cmd.Flags().StringVar(&createMaterializedFeatureReq.MaterializedFeature.CronSchedule, "cron-schedule", createMaterializedFeatureReq.MaterializedFeature.CronSchedule, `The quartz cron expression that defines the schedule of the materialization pipeline.`) // TODO: complex arg: cron_schedule_trigger cmd.Flags().StringVar(&createMaterializedFeatureReq.MaterializedFeature.MaterializedFeatureId, "materialized-feature-id", createMaterializedFeatureReq.MaterializedFeature.MaterializedFeatureId, `Server-assigned unique identifier for the materialized feature.`) // TODO: complex arg: offline_store_config @@ -1279,10 +1275,7 @@ func newUpdateFeature() *cobra.Command { cmd.Flags().StringVar(&updateFeatureReq.Feature.Description, "description", updateFeatureReq.Feature.Description, `The description of the feature.`) // TODO: array: entities - cmd.Flags().StringVar(&updateFeatureReq.Feature.FilterCondition, "filter-condition", updateFeatureReq.Feature.FilterCondition, `Deprecated: Use DeltaTableSource.filter_condition or KafkaSource.filter_condition instead.`) - // TODO: array: inputs // TODO: complex arg: lineage_context - // TODO: complex arg: time_window // TODO: complex arg: timeseries_column cmd.Use = "update-feature FULL_NAME UPDATE_MASK SOURCE FUNCTION" @@ -1504,7 +1497,6 @@ func newUpdateMaterializedFeature() *cobra.Command { cmd.Flags().Var(&updateMaterializedFeatureJson, "json", `either inline JSON string or @path/to/file.json with request body`) - cmd.Flags().StringVar(&updateMaterializedFeatureReq.MaterializedFeature.CronSchedule, "cron-schedule", updateMaterializedFeatureReq.MaterializedFeature.CronSchedule, `The quartz cron expression that defines the schedule of the materialization pipeline.`) // TODO: complex arg: cron_schedule_trigger cmd.Flags().StringVar(&updateMaterializedFeatureReq.MaterializedFeature.MaterializedFeatureId, "materialized-feature-id", updateMaterializedFeatureReq.MaterializedFeature.MaterializedFeatureId, `Server-assigned unique identifier for the materialized feature.`) // TODO: complex arg: offline_store_config diff --git a/cmd/workspace/genie/genie.go b/cmd/workspace/genie/genie.go index f2af834a048..292814fcf66 100644 --- a/cmd/workspace/genie/genie.go +++ b/cmd/workspace/genie/genie.go @@ -46,6 +46,7 @@ func New() *cobra.Command { cmd.AddCommand(newExecuteMessageAttachmentQuery()) cmd.AddCommand(newExecuteMessageQuery()) cmd.AddCommand(newGenerateDownloadFullQueryResult()) + cmd.AddCommand(newGenieCancelResponse()) cmd.AddCommand(newGenieCreateEvalRun()) cmd.AddCommand(newGenieGetEvalResultDetails()) cmd.AddCommand(newGenieGetEvalRun()) @@ -507,10 +508,8 @@ func newDownloadMessageAttachmentVisualization() *cobra.Command { var downloadMessageAttachmentVisualizationReq dashboards.DownloadMessageAttachmentVisualizationRequest cmd.Use = "download-message-attachment-visualization NAME" - cmd.Short = `*Beta* Download message attachment visualization.` - cmd.Long = `This command is in Beta and may change without notice. - -Download message attachment visualization. + cmd.Short = `Download message attachment visualization.` + cmd.Long = `Download message attachment visualization. Download a rendered image of a message visualization attachment. The response body is the raw PNG image, not a JSON payload. This is only available if the @@ -522,8 +521,8 @@ Download message attachment visualization. spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}/attachments/{attachment_id}.` cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PUBLIC_BETA" - cmd.Annotations["launch_stage_display"] = "Beta" + cmd.Annotations["launch_stage"] = "GA" + cmd.Annotations["launch_stage_display"] = "GA" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -778,6 +777,72 @@ func newGenerateDownloadFullQueryResult() *cobra.Command { return cmd } +// start genie-cancel-response command + +// Slice with functions to override default command behavior. +// Functions can be added from the `init()` function in manually curated files in this directory. +var genieCancelResponseOverrides []func( + *cobra.Command, + *dashboards.GenieCancelResponseRequest, +) + +func newGenieCancelResponse() *cobra.Command { + cmd := &cobra.Command{} + + var genieCancelResponseReq dashboards.GenieCancelResponseRequest + + cmd.Use = "genie-cancel-response AGENT_ID CONVERSATION_ID RESPONSE_ID" + cmd.Short = `Cancel Genie agent response.` + cmd.Long = `Cancel Genie agent response. + + Cancels an in-flight agent-mode response. response_id is the id returned in + the response.created event from the agent-mode responses endpoint. The + response stops at the next agent boundary and its terminal state is returned. + + Arguments: + AGENT_ID: The ID of the Genie agent (synonymous with the Genie space ID). + CONVERSATION_ID: The ID of the conversation containing the response. + RESPONSE_ID: The ID of the response to cancel (the id from the response.created + event).` + + cmd.Annotations = make(map[string]string) + cmd.Annotations["launch_stage"] = "GA" + cmd.Annotations["launch_stage_display"] = "GA" + + cmd.Args = func(cmd *cobra.Command, args []string) error { + check := root.ExactArgs(3) + return check(cmd, args) + } + + cmd.PreRunE = root.MustWorkspaceClient + cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { + ctx := cmd.Context() + w := cmdctx.WorkspaceClient(ctx) + + genieCancelResponseReq.AgentId = args[0] + genieCancelResponseReq.ConversationId = args[1] + genieCancelResponseReq.ResponseId = args[2] + + response, err := w.Genie.GenieCancelResponse(ctx, genieCancelResponseReq) + if err != nil { + return err + } + + return cmdio.Render(ctx, response) + } + + // Disable completions since they are not applicable. + // Can be overridden by manual implementation in `override.go`. + cmd.ValidArgsFunction = cobra.NoFileCompletions + + // Apply optional overrides to this command. + for _, fn := range genieCancelResponseOverrides { + fn(cmd, &genieCancelResponseReq) + } + + return cmd +} + // start genie-create-eval-run command // Slice with functions to override default command behavior. diff --git a/cmd/workspace/groups.go b/cmd/workspace/groups.go index 35e1bdd36c2..63c5f272a2e 100644 --- a/cmd/workspace/groups.go +++ b/cmd/workspace/groups.go @@ -62,7 +62,7 @@ func Groups() []cobra.Group { }, { ID: "sharing", - Title: "Delta Sharing", + Title: "Open Sharing", }, { ID: "settings", diff --git a/cmd/workspace/lakeview-embedded/lakeview-embedded.go b/cmd/workspace/lakeview-embedded/lakeview-embedded.go index 8c0d82339d7..d8edd269f9a 100644 --- a/cmd/workspace/lakeview-embedded/lakeview-embedded.go +++ b/cmd/workspace/lakeview-embedded/lakeview-embedded.go @@ -64,6 +64,9 @@ Read information of a published dashboard to mint an OAuth token. Get a required authorization details and scopes of a published dashboard to mint an OAuth token. + Requires one of the following entitlements: Workspace access, Databricks SQL + access, or Consumer access. + Arguments: DASHBOARD_ID: UUID identifying the published dashboard.` diff --git a/cmd/workspace/lakeview/lakeview.go b/cmd/workspace/lakeview/lakeview.go index 4b9949392d6..9804a18b72a 100644 --- a/cmd/workspace/lakeview/lakeview.go +++ b/cmd/workspace/lakeview/lakeview.go @@ -90,7 +90,9 @@ func newCreate() *cobra.Command { cmd.Short = `Create dashboard.` cmd.Long = `Create dashboard. - Create a draft dashboard.` + Create a draft dashboard. + + Requires the Databricks SQL access entitlement.` cmd.Annotations = make(map[string]string) cmd.Annotations["launch_stage"] = "GA" @@ -467,6 +469,8 @@ func newGet() *cobra.Command { Get a draft dashboard. + Requires the Databricks SQL access entitlement. + Arguments: DASHBOARD_ID: UUID identifying the dashboard.` @@ -526,6 +530,9 @@ func newGetPublished() *cobra.Command { Get the current published dashboard. + Requires one of the following entitlements: Workspace access, Databricks SQL + access, or Consumer access. + Arguments: DASHBOARD_ID: UUID identifying the published dashboard.` @@ -716,7 +723,11 @@ func newList() *cobra.Command { cmd.Use = "list" cmd.Short = `List dashboards.` - cmd.Long = `List dashboards.` + cmd.Long = `List dashboards. + + List dashboards. + + Requires the Databricks SQL access entitlement.` cmd.Annotations = make(map[string]string) cmd.Annotations["launch_stage"] = "GA" @@ -1016,6 +1027,8 @@ func newPublish() *cobra.Command { Publish the current draft dashboard. + Requires the Databricks SQL access entitlement. + Arguments: DASHBOARD_ID: UUID identifying the dashboard to be published.` @@ -1090,6 +1103,8 @@ func newRevert() *cobra.Command { Revert a dashboard's definition in draft mode to the last published version. + Requires the Databricks SQL access entitlement. + Arguments: DASHBOARD_ID: UUID identifying the dashboard.` @@ -1161,6 +1176,8 @@ func newTrash() *cobra.Command { Trash a dashboard. + Requires the Databricks SQL access entitlement. + Arguments: DASHBOARD_ID: UUID identifying the dashboard.` @@ -1219,6 +1236,8 @@ func newUnpublish() *cobra.Command { Unpublish the dashboard. + Requires the Databricks SQL access entitlement. + Arguments: DASHBOARD_ID: UUID identifying the published dashboard.` @@ -1287,6 +1306,8 @@ func newUpdate() *cobra.Command { Update a draft dashboard. + Requires the Databricks SQL access entitlement. + Arguments: DASHBOARD_ID: UUID identifying the dashboard.` diff --git a/cmd/workspace/policies/policies.go b/cmd/workspace/policies/policies.go index 7c3e903a20c..1c77caf96dc 100644 --- a/cmd/workspace/policies/policies.go +++ b/cmd/workspace/policies/policies.go @@ -86,7 +86,11 @@ func newCreatePolicy() *cobra.Command { EXTERNAL_LOCATION, EXTERNAL_METADATA, FUNCTION, + MCP_SERVICE, METASTORE, + MODEL, + MODEL_PROVIDER_SERVICE, + MODEL_SERVICE, PIPELINE, PROVIDER, RECIPIENT, @@ -120,7 +124,11 @@ func newCreatePolicy() *cobra.Command { EXTERNAL_LOCATION, EXTERNAL_METADATA, FUNCTION, + MCP_SERVICE, METASTORE, + MODEL, + MODEL_PROVIDER_SERVICE, + MODEL_SERVICE, PIPELINE, PROVIDER, RECIPIENT, @@ -454,7 +462,11 @@ func newUpdatePolicy() *cobra.Command { EXTERNAL_LOCATION, EXTERNAL_METADATA, FUNCTION, + MCP_SERVICE, METASTORE, + MODEL, + MODEL_PROVIDER_SERVICE, + MODEL_SERVICE, PIPELINE, PROVIDER, RECIPIENT, @@ -491,7 +503,11 @@ func newUpdatePolicy() *cobra.Command { EXTERNAL_LOCATION, EXTERNAL_METADATA, FUNCTION, + MCP_SERVICE, METASTORE, + MODEL, + MODEL_PROVIDER_SERVICE, + MODEL_SERVICE, PIPELINE, PROVIDER, RECIPIENT, diff --git a/cmd/workspace/postgres/postgres.go b/cmd/workspace/postgres/postgres.go index 7d3ae59f375..92a30ceae6d 100644 --- a/cmd/workspace/postgres/postgres.go +++ b/cmd/workspace/postgres/postgres.go @@ -58,6 +58,7 @@ func New() *cobra.Command { cmd.AddCommand(newCreateEndpoint()) cmd.AddCommand(newCreateProject()) cmd.AddCommand(newCreateRole()) + cmd.AddCommand(newCreateSnapshot()) cmd.AddCommand(newCreateSyncedTable()) cmd.AddCommand(newDeleteBranch()) cmd.AddCommand(newDeleteCatalog()) @@ -67,6 +68,7 @@ func New() *cobra.Command { cmd.AddCommand(newDeleteEndpoint()) cmd.AddCommand(newDeleteProject()) cmd.AddCommand(newDeleteRole()) + cmd.AddCommand(newDeleteSnapshot()) cmd.AddCommand(newDeleteSyncedTable()) cmd.AddCommand(newGenerateDatabaseCredential()) cmd.AddCommand(newGetBranch()) @@ -79,6 +81,8 @@ func New() *cobra.Command { cmd.AddCommand(newGetOperation()) cmd.AddCommand(newGetProject()) cmd.AddCommand(newGetRole()) + cmd.AddCommand(newGetSnapshot()) + cmd.AddCommand(newGetSnapshotSchedule()) cmd.AddCommand(newGetSyncedTable()) cmd.AddCommand(newListBranches()) cmd.AddCommand(newListCdfConfigs()) @@ -87,6 +91,7 @@ func New() *cobra.Command { cmd.AddCommand(newListEndpoints()) cmd.AddCommand(newListProjects()) cmd.AddCommand(newListRoles()) + cmd.AddCommand(newListSnapshots()) cmd.AddCommand(newUndeleteBranch()) cmd.AddCommand(newUndeleteProject()) cmd.AddCommand(newUpdateBranch()) @@ -95,6 +100,7 @@ func New() *cobra.Command { cmd.AddCommand(newUpdateEndpoint()) cmd.AddCommand(newUpdateProject()) cmd.AddCommand(newUpdateRole()) + cmd.AddCommand(newUpdateSnapshotSchedule()) // Apply optional overrides to this command. for _, fn := range cmdOverrides { @@ -1125,6 +1131,133 @@ func newCreateRole() *cobra.Command { return cmd } +// start create-snapshot command + +// Slice with functions to override default command behavior. +// Functions can be added from the `init()` function in manually curated files in this directory. +var createSnapshotOverrides []func( + *cobra.Command, + *postgres.CreateSnapshotRequest, +) + +func newCreateSnapshot() *cobra.Command { + cmd := &cobra.Command{} + + var createSnapshotReq postgres.CreateSnapshotRequest + createSnapshotReq.Snapshot = postgres.Snapshot{} + var createSnapshotJson flags.JsonFlag + + var createSnapshotSkipWait bool + var createSnapshotTimeout time.Duration + + cmd.Flags().BoolVar(&createSnapshotSkipWait, "no-wait", createSnapshotSkipWait, `do not wait to reach DONE state`) + cmd.Flags().DurationVar(&createSnapshotTimeout, "timeout", 0, `maximum amount of time to reach DONE state`) + + cmd.Flags().Var(&createSnapshotJson, "json", `either inline JSON string or @path/to/file.json with request body`) + + cmd.Flags().StringVar(&createSnapshotReq.Snapshot.Name, "name", createSnapshotReq.Snapshot.Name, `The resource name of the snapshot.`) + // TODO: complex arg: spec + // TODO: complex arg: status + + cmd.Use = "create-snapshot PARENT SNAPSHOT_ID" + cmd.Short = `Create a Snapshot.` + cmd.Long = `Create a Snapshot. + + Creates a snapshot, an immutable point-in-time copy of a branch's data, within + the project. + + This is a long-running operation. By default, the command waits for the + operation to complete. Use --no-wait to return immediately with the raw + operation details. The operation's 'name' field can then be used to poll for + completion using the get-operation command. + + Arguments: + PARENT: The project in which to create the snapshot. Format: projects/{project_id} + SNAPSHOT_ID: Client-chosen ID for the snapshot. It becomes the final segment of the + snapshot resource name and cannot be changed after creation.` + + // This command is being previewed; hide from help output. + cmd.Hidden = true + + cmd.Annotations = make(map[string]string) + cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" + cmd.Annotations["launch_stage_display"] = "Private Preview" + + cmd.Args = func(cmd *cobra.Command, args []string) error { + check := root.ExactArgs(2) + return check(cmd, args) + } + + cmd.PreRunE = root.MustWorkspaceClient + cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { + ctx := cmd.Context() + w := cmdctx.WorkspaceClient(ctx) + + if cmd.Flags().Changed("json") { + diags := createSnapshotJson.Unmarshal(&createSnapshotReq.Snapshot) + if diags.HasError() { + return diags.Error() + } + if len(diags) > 0 { + err := cmdio.RenderDiagnostics(ctx, diags) + if err != nil { + return err + } + } + } + createSnapshotReq.Parent = args[0] + createSnapshotReq.SnapshotId = args[1] + + // Determine which mode to execute based on flags. + switch { + case createSnapshotSkipWait: + wait, err := w.Postgres.CreateSnapshot(ctx, createSnapshotReq) + if err != nil { + return err + } + + // Return operation immediately without waiting. + operation, err := w.Postgres.GetOperation(ctx, postgres.GetOperationRequest{ + Name: wait.Name(), + }) + if err != nil { + return err + } + return cmdio.Render(ctx, operation) + + default: + wait, err := w.Postgres.CreateSnapshot(ctx, createSnapshotReq) + if err != nil { + return err + } + + // Show spinner while waiting for completion. + sp := cmdio.NewSpinner(ctx) + sp.Update("Waiting for create-snapshot to complete...") + + // Wait for completion. + opts := api.WithTimeout(createSnapshotTimeout) + response, err := wait.Wait(ctx, opts) + if err != nil { + return err + } + sp.Close() + return cmdio.Render(ctx, response) + } + } + + // Disable completions since they are not applicable. + // Can be overridden by manual implementation in `override.go`. + cmd.ValidArgsFunction = cobra.NoFileCompletions + + // Apply optional overrides to this command. + for _, fn := range createSnapshotOverrides { + fn(cmd, &createSnapshotReq) + } + + return cmd +} + // start create-synced-table command // Slice with functions to override default command behavior. @@ -2082,6 +2215,111 @@ func newDeleteRole() *cobra.Command { return cmd } +// start delete-snapshot command + +// Slice with functions to override default command behavior. +// Functions can be added from the `init()` function in manually curated files in this directory. +var deleteSnapshotOverrides []func( + *cobra.Command, + *postgres.DeleteSnapshotRequest, +) + +func newDeleteSnapshot() *cobra.Command { + cmd := &cobra.Command{} + + var deleteSnapshotReq postgres.DeleteSnapshotRequest + + var deleteSnapshotSkipWait bool + var deleteSnapshotTimeout time.Duration + + cmd.Flags().BoolVar(&deleteSnapshotSkipWait, "no-wait", deleteSnapshotSkipWait, `do not wait to reach DONE state`) + cmd.Flags().DurationVar(&deleteSnapshotTimeout, "timeout", 0, `maximum amount of time to reach DONE state`) + + cmd.Use = "delete-snapshot NAME" + cmd.Short = `Delete a Snapshot.` + cmd.Long = `Delete a Snapshot. + + Deletes the specified snapshot. + + This is a long-running operation. By default, the command waits for the + operation to complete. Use --no-wait to return immediately with the raw + operation details. The operation's 'name' field can then be used to poll for + completion using the get-operation command. + + Arguments: + NAME: The resource name of the snapshot to delete. Format: + projects/{project_id}/snapshots/{snapshot_id}` + + // This command is being previewed; hide from help output. + cmd.Hidden = true + + cmd.Annotations = make(map[string]string) + cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" + cmd.Annotations["launch_stage_display"] = "Private Preview" + + cmd.Args = func(cmd *cobra.Command, args []string) error { + check := root.ExactArgs(1) + return check(cmd, args) + } + + cmd.PreRunE = root.MustWorkspaceClient + cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { + ctx := cmd.Context() + w := cmdctx.WorkspaceClient(ctx) + + deleteSnapshotReq.Name = args[0] + + // Determine which mode to execute based on flags. + switch { + case deleteSnapshotSkipWait: + wait, err := w.Postgres.DeleteSnapshot(ctx, deleteSnapshotReq) + if err != nil { + return err + } + + // Return operation immediately without waiting. + operation, err := w.Postgres.GetOperation(ctx, postgres.GetOperationRequest{ + Name: wait.Name(), + }) + if err != nil { + return err + } + return cmdio.Render(ctx, operation) + + default: + wait, err := w.Postgres.DeleteSnapshot(ctx, deleteSnapshotReq) + if err != nil { + return err + } + + // Show spinner while waiting for completion. + sp := cmdio.NewSpinner(ctx) + sp.Update("Waiting for delete-snapshot to complete...") + + // Wait for completion. + opts := api.WithTimeout(deleteSnapshotTimeout) + + err = wait.Wait(ctx, opts) + if err != nil { + return err + } + sp.Close() + return nil + } + } + + // Disable completions since they are not applicable. + // Can be overridden by manual implementation in `override.go`. + cmd.ValidArgsFunction = cobra.NoFileCompletions + + // Apply optional overrides to this command. + for _, fn := range deleteSnapshotOverrides { + fn(cmd, &deleteSnapshotReq) + } + + return cmd +} + // start delete-synced-table command // Slice with functions to override default command behavior. @@ -2901,6 +3139,133 @@ func newGetRole() *cobra.Command { return cmd } +// start get-snapshot command + +// Slice with functions to override default command behavior. +// Functions can be added from the `init()` function in manually curated files in this directory. +var getSnapshotOverrides []func( + *cobra.Command, + *postgres.GetSnapshotRequest, +) + +func newGetSnapshot() *cobra.Command { + cmd := &cobra.Command{} + + var getSnapshotReq postgres.GetSnapshotRequest + + cmd.Use = "get-snapshot NAME" + cmd.Short = `Get a Snapshot.` + cmd.Long = `Get a Snapshot. + + Retrieves information about the specified snapshot. + + Arguments: + NAME: The resource name of the snapshot to retrieve. Format: + projects/{project_id}/snapshots/{snapshot_id}` + + // This command is being previewed; hide from help output. + cmd.Hidden = true + + cmd.Annotations = make(map[string]string) + cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" + cmd.Annotations["launch_stage_display"] = "Private Preview" + + cmd.Args = func(cmd *cobra.Command, args []string) error { + check := root.ExactArgs(1) + return check(cmd, args) + } + + cmd.PreRunE = root.MustWorkspaceClient + cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { + ctx := cmd.Context() + w := cmdctx.WorkspaceClient(ctx) + + getSnapshotReq.Name = args[0] + + response, err := w.Postgres.GetSnapshot(ctx, getSnapshotReq) + if err != nil { + return err + } + + return cmdio.Render(ctx, response) + } + + // Disable completions since they are not applicable. + // Can be overridden by manual implementation in `override.go`. + cmd.ValidArgsFunction = cobra.NoFileCompletions + + // Apply optional overrides to this command. + for _, fn := range getSnapshotOverrides { + fn(cmd, &getSnapshotReq) + } + + return cmd +} + +// start get-snapshot-schedule command + +// Slice with functions to override default command behavior. +// Functions can be added from the `init()` function in manually curated files in this directory. +var getSnapshotScheduleOverrides []func( + *cobra.Command, + *postgres.GetSnapshotScheduleRequest, +) + +func newGetSnapshotSchedule() *cobra.Command { + cmd := &cobra.Command{} + + var getSnapshotScheduleReq postgres.GetSnapshotScheduleRequest + + cmd.Use = "get-snapshot-schedule NAME" + cmd.Short = `Get a Snapshot Schedule.` + cmd.Long = `Get a Snapshot Schedule. + + Retrieves the snapshot schedule for a branch. A branch with no configured + schedule returns an empty schedule (not NOT_FOUND). + + Arguments: + NAME: The resource name of the branch's snapshot schedule. Format: + projects/{project_id}/branches/{branch_id}/snapshot-schedule` + + // This command is being previewed; hide from help output. + cmd.Hidden = true + + cmd.Annotations = make(map[string]string) + cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" + cmd.Annotations["launch_stage_display"] = "Private Preview" + + cmd.Args = func(cmd *cobra.Command, args []string) error { + check := root.ExactArgs(1) + return check(cmd, args) + } + + cmd.PreRunE = root.MustWorkspaceClient + cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { + ctx := cmd.Context() + w := cmdctx.WorkspaceClient(ctx) + + getSnapshotScheduleReq.Name = args[0] + + response, err := w.Postgres.GetSnapshotSchedule(ctx, getSnapshotScheduleReq) + if err != nil { + return err + } + + return cmdio.Render(ctx, response) + } + + // Disable completions since they are not applicable. + // Can be overridden by manual implementation in `override.go`. + cmd.ValidArgsFunction = cobra.NoFileCompletions + + // Apply optional overrides to this command. + for _, fn := range getSnapshotScheduleOverrides { + fn(cmd, &getSnapshotScheduleReq) + } + + return cmd +} + // start get-synced-table command // Slice with functions to override default command behavior. @@ -3499,6 +3864,84 @@ func newListRoles() *cobra.Command { return cmd } +// start list-snapshots command + +// Slice with functions to override default command behavior. +// Functions can be added from the `init()` function in manually curated files in this directory. +var listSnapshotsOverrides []func( + *cobra.Command, + *postgres.ListSnapshotsRequest, +) + +func newListSnapshots() *cobra.Command { + cmd := &cobra.Command{} + + var listSnapshotsReq postgres.ListSnapshotsRequest + // Registered for all paginated methods. Validated at call time in the + // method-call template. Paginated list methods never have Wait or LRO + // branches, so the method-call path is always reached. + var listSnapshotsLimit int + + cmd.Flags().IntVar(&listSnapshotsReq.PageSize, "page-size", listSnapshotsReq.PageSize, `Maximum number of snapshots to return per page.`) + + // Limit flag for total result capping. + cmd.Flags().IntVar(&listSnapshotsLimit, "limit", 0, `Maximum number of results to return.`) + + // Hidden pagination flags (internal API parameters). + cmd.Flags().StringVar(&listSnapshotsReq.PageToken, "page-token", listSnapshotsReq.PageToken, `Pagination token.`) + cmd.Flags().Lookup("page-token").Hidden = true + + cmd.Use = "list-snapshots PARENT" + cmd.Short = `List Snapshots.` + cmd.Long = `List Snapshots. + + Returns a paginated list of snapshots in the project. + + Arguments: + PARENT: The project that owns the snapshots. Format: projects/{project_id}` + + // This command is being previewed; hide from help output. + cmd.Hidden = true + + cmd.Annotations = make(map[string]string) + cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" + cmd.Annotations["launch_stage_display"] = "Private Preview" + + cmd.Args = func(cmd *cobra.Command, args []string) error { + check := root.ExactArgs(1) + return check(cmd, args) + } + + cmd.PreRunE = root.MustWorkspaceClient + cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { + ctx := cmd.Context() + w := cmdctx.WorkspaceClient(ctx) + + listSnapshotsReq.Parent = args[0] + + response := w.Postgres.ListSnapshots(ctx, listSnapshotsReq) + if listSnapshotsLimit < 0 { + return fmt.Errorf("--limit must be a non-negative integer, got %d", listSnapshotsLimit) + } + if listSnapshotsLimit > 0 { + ctx = cmdio.WithLimit(ctx, listSnapshotsLimit) + } + + return cmdio.RenderIterator(ctx, response) + } + + // Disable completions since they are not applicable. + // Can be overridden by manual implementation in `override.go`. + cmd.ValidArgsFunction = cobra.NoFileCompletions + + // Apply optional overrides to this command. + for _, fn := range listSnapshotsOverrides { + fn(cmd, &listSnapshotsReq) + } + + return cmd +} + // start undelete-branch command // Slice with functions to override default command behavior. @@ -4469,4 +4912,134 @@ func newUpdateRole() *cobra.Command { return cmd } +// start update-snapshot-schedule command + +// Slice with functions to override default command behavior. +// Functions can be added from the `init()` function in manually curated files in this directory. +var updateSnapshotScheduleOverrides []func( + *cobra.Command, + *postgres.UpdateSnapshotScheduleRequest, +) + +func newUpdateSnapshotSchedule() *cobra.Command { + cmd := &cobra.Command{} + + var updateSnapshotScheduleReq postgres.UpdateSnapshotScheduleRequest + updateSnapshotScheduleReq.SnapshotSchedule = postgres.SnapshotSchedule{} + var updateSnapshotScheduleJson flags.JsonFlag + + var updateSnapshotScheduleSkipWait bool + var updateSnapshotScheduleTimeout time.Duration + + cmd.Flags().BoolVar(&updateSnapshotScheduleSkipWait, "no-wait", updateSnapshotScheduleSkipWait, `do not wait to reach DONE state`) + cmd.Flags().DurationVar(&updateSnapshotScheduleTimeout, "timeout", 0, `maximum amount of time to reach DONE state`) + + cmd.Flags().Var(&updateSnapshotScheduleJson, "json", `either inline JSON string or @path/to/file.json with request body`) + + cmd.Flags().StringVar(&updateSnapshotScheduleReq.SnapshotSchedule.Name, "name", updateSnapshotScheduleReq.SnapshotSchedule.Name, `The resource name of the branch's snapshot schedule.`) + // TODO: array: schedule + + cmd.Use = "update-snapshot-schedule NAME UPDATE_MASK" + cmd.Short = `Update a Snapshot Schedule.` + cmd.Long = `Update a Snapshot Schedule. + + Sets the snapshot schedule for a branch. The schedule field is replaced + wholesale; an empty schedule disables automatic snapshots. + + This is a long-running operation. By default, the command waits for the + operation to complete. Use --no-wait to return immediately with the raw + operation details. The operation's 'name' field can then be used to poll for + completion using the get-operation command. + + Arguments: + NAME: The resource name of the branch's snapshot schedule. Format: + projects/{project_id}/branches/{branch_id}/snapshot-schedule + UPDATE_MASK: Fields to update. The only updatable path is schedule, which replaces + the entire set of cadences.` + + // This command is being previewed; hide from help output. + cmd.Hidden = true + + cmd.Annotations = make(map[string]string) + cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" + cmd.Annotations["launch_stage_display"] = "Private Preview" + + cmd.Args = func(cmd *cobra.Command, args []string) error { + check := root.ExactArgs(2) + return check(cmd, args) + } + + cmd.PreRunE = root.MustWorkspaceClient + cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { + ctx := cmd.Context() + w := cmdctx.WorkspaceClient(ctx) + + if cmd.Flags().Changed("json") { + diags := updateSnapshotScheduleJson.Unmarshal(&updateSnapshotScheduleReq.SnapshotSchedule) + if diags.HasError() { + return diags.Error() + } + if len(diags) > 0 { + err := cmdio.RenderDiagnostics(ctx, diags) + if err != nil { + return err + } + } + } + updateSnapshotScheduleReq.Name = args[0] + if args[1] != "" { + updateMaskArray := strings.Split(args[1], ",") + updateSnapshotScheduleReq.UpdateMask = *fieldmask.New(updateMaskArray) + } + + // Determine which mode to execute based on flags. + switch { + case updateSnapshotScheduleSkipWait: + wait, err := w.Postgres.UpdateSnapshotSchedule(ctx, updateSnapshotScheduleReq) + if err != nil { + return err + } + + // Return operation immediately without waiting. + operation, err := w.Postgres.GetOperation(ctx, postgres.GetOperationRequest{ + Name: wait.Name(), + }) + if err != nil { + return err + } + return cmdio.Render(ctx, operation) + + default: + wait, err := w.Postgres.UpdateSnapshotSchedule(ctx, updateSnapshotScheduleReq) + if err != nil { + return err + } + + // Show spinner while waiting for completion. + sp := cmdio.NewSpinner(ctx) + sp.Update("Waiting for update-snapshot-schedule to complete...") + + // Wait for completion. + opts := api.WithTimeout(updateSnapshotScheduleTimeout) + response, err := wait.Wait(ctx, opts) + if err != nil { + return err + } + sp.Close() + return cmdio.Render(ctx, response) + } + } + + // Disable completions since they are not applicable. + // Can be overridden by manual implementation in `override.go`. + cmd.ValidArgsFunction = cobra.NoFileCompletions + + // Apply optional overrides to this command. + for _, fn := range updateSnapshotScheduleOverrides { + fn(cmd, &updateSnapshotScheduleReq) + } + + return cmd +} + // end service Postgres diff --git a/cmd/workspace/workspace-iam-v2/workspace-iam-v2.go b/cmd/workspace/workspace-iam-v2/workspace-iam-v2.go index 992a27e35d7..9139ea51e8a 100644 --- a/cmd/workspace/workspace-iam-v2/workspace-iam-v2.go +++ b/cmd/workspace/workspace-iam-v2/workspace-iam-v2.go @@ -50,6 +50,9 @@ These APIs are used to manage identities and the workspace access of these cmd.AddCommand(newDeleteWorkspaceAssignmentDetailProxy()) cmd.AddCommand(newDeleteWorkspaceAssignmentProxy()) cmd.AddCommand(newGetDirectGroupMemberProxy()) + cmd.AddCommand(newGetExternalGroupProxy()) + cmd.AddCommand(newGetExternalServicePrincipalProxy()) + cmd.AddCommand(newGetExternalUserProxy()) cmd.AddCommand(newGetGroupProxy()) cmd.AddCommand(newGetServicePrincipalProxy()) cmd.AddCommand(newGetUserProxy()) @@ -101,8 +104,10 @@ func newCreateDirectGroupMemberProxy() *cobra.Command { cmd.Flags().Var(&createDirectGroupMemberProxyJson, "json", `either inline JSON string or @path/to/file.json with request body`) cmd.Use = "create-direct-group-member-proxy GROUP_ID PRINCIPAL_ID" - cmd.Short = `Create a direct group membership.` - cmd.Long = `Create a direct group membership. + cmd.Short = `*Beta* Create a direct group membership.` + cmd.Long = `This command is in Beta and may change without notice. + +Create a direct group membership. Creates a group membership (assigns a principal to a group). @@ -110,12 +115,9 @@ func newCreateDirectGroupMemberProxy() *cobra.Command { GROUP_ID: Required. Internal ID of the group in Databricks. PRINCIPAL_ID: Internal ID of the principal in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("json") { @@ -201,8 +203,10 @@ func newCreateGroupProxy() *cobra.Command { cmd.Flags().StringVar(&createGroupProxyReq.Group.GroupName, "group-name", createGroupProxyReq.Group.GroupName, `Display name of the group.`) cmd.Use = "create-group-proxy" - cmd.Short = `Create a group in the account.` - cmd.Long = `Create a group in the account. + cmd.Short = `*Beta* Create a group in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Create a group in the account. Creates a local group in the Databricks account that parents the calling workspace and returns the created group. A local group is one that is not @@ -214,12 +218,9 @@ func newCreateGroupProxy() *cobra.Command { ResolveGroup; to read an existing external identity, use the ExternalGroup resource.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(0) @@ -285,8 +286,10 @@ func newCreateServicePrincipalProxy() *cobra.Command { cmd.Flags().StringVar(&createServicePrincipalProxyReq.ServicePrincipal.ExternalId, "external-id", createServicePrincipalProxyReq.ServicePrincipal.ExternalId, `ExternalId of the service principal in the customer's IdP.`) cmd.Use = "create-service-principal-proxy DISPLAY_NAME ACCOUNT_SP_STATUS" - cmd.Short = `Create a service principal in the account.` - cmd.Long = `Create a service principal in the account. + cmd.Short = `*Beta* Create a service principal in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Create a service principal in the account. Creates a local service principal in the Databricks account that parents the calling workspace and returns the created service principal. A local service @@ -303,12 +306,9 @@ func newCreateServicePrincipalProxy() *cobra.Command { ACCOUNT_SP_STATUS: The activity status of a service principal in a Databricks account. Supported values: [ACTIVE, INACTIVE]` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("json") { @@ -391,8 +391,10 @@ func newCreateUserProxy() *cobra.Command { cmd.Flags().StringVar(&createUserProxyReq.User.ExternalId, "external-id", createUserProxyReq.User.ExternalId, `ExternalId of the user in the customer's IdP.`) cmd.Use = "create-user-proxy USERNAME FULL_NAME ACCOUNT_USER_STATUS" - cmd.Short = `Create a user in the account.` - cmd.Long = `Create a user in the account. + cmd.Short = `*Beta* Create a user in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Create a user in the account. Creates a local user in the Databricks account that parents the calling workspace and returns the created user. A local user is one that is not synced @@ -410,12 +412,9 @@ func newCreateUserProxy() *cobra.Command { ACCOUNT_USER_STATUS: The activity status of a user in a Databricks account. Supported values: [ACTIVE, INACTIVE]` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("json") { @@ -510,10 +509,7 @@ func newCreateWorkspaceAssignmentDetailProxy() *cobra.Command { cmd.Long = `Create a workspace assignment detail for a workspace. Creates a workspace assignment detail for a principal in the calling - workspace. Entitlements are granted one at a time rather than atomically. If - the request fails partway through, the principal stays assigned to the - workspace with only some of the requested entitlements. Get the assignment - detail afterwards to confirm which entitlements were granted. + workspace. Arguments: PRINCIPAL_ID: The internal ID of the principal (user/sp/group) in Databricks.` @@ -604,8 +600,10 @@ func newCreateWorkspaceAssignmentProxy() *cobra.Command { // TODO: array: entitlements cmd.Use = "create-workspace-assignment-proxy PRINCIPAL_ID" - cmd.Short = `Create a workspace assignment for a workspace.` - cmd.Long = `Create a workspace assignment for a workspace. + cmd.Short = `*Beta* Create a workspace assignment for a workspace.` + cmd.Long = `This command is in Beta and may change without notice. + +Create a workspace assignment for a workspace. Creates a workspace assignment for a principal in the calling workspace. Entitlements are granted one at a time rather than atomically. If the request @@ -616,12 +614,9 @@ func newCreateWorkspaceAssignmentProxy() *cobra.Command { Arguments: PRINCIPAL_ID: The internal ID of the principal (user/sp/group) in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("json") { @@ -695,8 +690,10 @@ func newDeleteDirectGroupMemberProxy() *cobra.Command { var deleteDirectGroupMemberProxyReq iamv2.DeleteDirectGroupMemberProxyRequest cmd.Use = "delete-direct-group-member-proxy GROUP_ID PRINCIPAL_ID" - cmd.Short = `Delete a direct group membership.` - cmd.Long = `Delete a direct group membership. + cmd.Short = `*Beta* Delete a direct group membership.` + cmd.Long = `This command is in Beta and may change without notice. + +Delete a direct group membership. Deletes a group membership (unassigns a principal from a group). @@ -704,12 +701,9 @@ func newDeleteDirectGroupMemberProxy() *cobra.Command { GROUP_ID: Required. Internal ID of the group in Databricks. PRINCIPAL_ID: Required. Internal ID of the principal to be unassigned from the group.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(2) @@ -765,8 +759,10 @@ func newDeleteGroupProxy() *cobra.Command { var deleteGroupProxyReq iamv2.DeleteGroupProxyRequest cmd.Use = "delete-group-proxy GROUP_ID" - cmd.Short = `Delete a group in the account.` - cmd.Long = `Delete a group in the account. + cmd.Short = `*Beta* Delete a group in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Delete a group in the account. Deletes a group by its internal ID from the Databricks account that parents the calling workspace. @@ -774,12 +770,9 @@ func newDeleteGroupProxy() *cobra.Command { Arguments: GROUP_ID: Required. Internal ID of the group in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -827,8 +820,10 @@ func newDeleteServicePrincipalProxy() *cobra.Command { var deleteServicePrincipalProxyReq iamv2.DeleteServicePrincipalProxyRequest cmd.Use = "delete-service-principal-proxy SERVICE_PRINCIPAL_ID" - cmd.Short = `Delete a service principal in the account.` - cmd.Long = `Delete a service principal in the account. + cmd.Short = `*Beta* Delete a service principal in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Delete a service principal in the account. Deletes a service principal by its internal ID from the Databricks account that parents the calling workspace. @@ -836,12 +831,9 @@ func newDeleteServicePrincipalProxy() *cobra.Command { Arguments: SERVICE_PRINCIPAL_ID: Required. Internal ID of the service principal in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -889,8 +881,10 @@ func newDeleteUserProxy() *cobra.Command { var deleteUserProxyReq iamv2.DeleteUserProxyRequest cmd.Use = "delete-user-proxy USER_ID" - cmd.Short = `Delete a user in the account.` - cmd.Long = `Delete a user in the account. + cmd.Short = `*Beta* Delete a user in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Delete a user in the account. Deletes a user by its internal ID from the Databricks account that parents the calling workspace. @@ -898,12 +892,9 @@ func newDeleteUserProxy() *cobra.Command { Arguments: USER_ID: Required. Internal ID of the user in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -1020,8 +1011,10 @@ func newDeleteWorkspaceAssignmentProxy() *cobra.Command { var deleteWorkspaceAssignmentProxyReq iamv2.DeleteWorkspaceAssignmentProxyRequest cmd.Use = "delete-workspace-assignment-proxy PRINCIPAL_ID" - cmd.Short = `Delete a workspace assignment for a workspace.` - cmd.Long = `Delete a workspace assignment for a workspace. + cmd.Short = `*Beta* Delete a workspace assignment for a workspace.` + cmd.Long = `This command is in Beta and may change without notice. + +Delete a workspace assignment for a workspace. Deletes a workspace assignment for a principal in the calling workspace, revoking all of its entitlements. Entitlements are revoked one at a time @@ -1032,12 +1025,9 @@ func newDeleteWorkspaceAssignmentProxy() *cobra.Command { PRINCIPAL_ID: Required. ID of the principal in Databricks to delete workspace assignment for.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -1088,8 +1078,10 @@ func newGetDirectGroupMemberProxy() *cobra.Command { var getDirectGroupMemberProxyReq iamv2.GetDirectGroupMemberProxyRequest cmd.Use = "get-direct-group-member-proxy GROUP_ID PRINCIPAL_ID" - cmd.Short = `Get a direct group member.` - cmd.Long = `Get a direct group member. + cmd.Short = `*Beta* Get a direct group member.` + cmd.Long = `This command is in Beta and may change without notice. + +Get a direct group member. Gets a provisioned direct member of a group. @@ -1098,12 +1090,9 @@ func newGetDirectGroupMemberProxy() *cobra.Command { PRINCIPAL_ID: Required. Internal ID of the principal belonging to the group in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(2) @@ -1145,6 +1134,202 @@ func newGetDirectGroupMemberProxy() *cobra.Command { return cmd } +// start get-external-group-proxy command + +// Slice with functions to override default command behavior. +// Functions can be added from the `init()` function in manually curated files in this directory. +var getExternalGroupProxyOverrides []func( + *cobra.Command, + *iamv2.GetExternalGroupProxyRequest, +) + +func newGetExternalGroupProxy() *cobra.Command { + cmd := &cobra.Command{} + + var getExternalGroupProxyReq iamv2.GetExternalGroupProxyRequest + + cmd.Use = "get-external-group-proxy NAME" + cmd.Short = `*Beta* Get an external group in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Get an external group in the account. + + Retrieves an external group with the given external ID from the customer's + IdP. If the group does not exist, it will be created in the account. If the + customer is not onboarded onto Automatic Identity Management (AIM), this will + return an error. Workspace-scoped variant for workspace-authenticated callers. + + Arguments: + NAME: Required. The resource name of the external group. Format: + external-groups/{external_group_id}` + + cmd.Annotations = make(map[string]string) + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" + + cmd.Args = func(cmd *cobra.Command, args []string) error { + check := root.ExactArgs(1) + return check(cmd, args) + } + + cmd.PreRunE = root.MustWorkspaceClient + cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { + ctx := cmd.Context() + w := cmdctx.WorkspaceClient(ctx) + + getExternalGroupProxyReq.Name = args[0] + + response, err := w.WorkspaceIamV2.GetExternalGroupProxy(ctx, getExternalGroupProxyReq) + if err != nil { + return err + } + + return cmdio.Render(ctx, response) + } + + // Disable completions since they are not applicable. + // Can be overridden by manual implementation in `override.go`. + cmd.ValidArgsFunction = cobra.NoFileCompletions + + // Apply optional overrides to this command. + for _, fn := range getExternalGroupProxyOverrides { + fn(cmd, &getExternalGroupProxyReq) + } + + return cmd +} + +// start get-external-service-principal-proxy command + +// Slice with functions to override default command behavior. +// Functions can be added from the `init()` function in manually curated files in this directory. +var getExternalServicePrincipalProxyOverrides []func( + *cobra.Command, + *iamv2.GetExternalServicePrincipalProxyRequest, +) + +func newGetExternalServicePrincipalProxy() *cobra.Command { + cmd := &cobra.Command{} + + var getExternalServicePrincipalProxyReq iamv2.GetExternalServicePrincipalProxyRequest + + cmd.Use = "get-external-service-principal-proxy NAME" + cmd.Short = `*Beta* Get an external service principal in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Get an external service principal in the account. + + Retrieves an external service principal with the given external ID from the + customer's IdP. If the service principal does not exist, it will be created. + If the customer is not onboarded onto Automatic Identity Management (AIM), + this will return an error. Workspace-scoped variant for + workspace-authenticated callers. + + Arguments: + NAME: Required. The resource name of the external service principal. Format: + external-service-principals/{external_service_principal_id}` + + cmd.Annotations = make(map[string]string) + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" + + cmd.Args = func(cmd *cobra.Command, args []string) error { + check := root.ExactArgs(1) + return check(cmd, args) + } + + cmd.PreRunE = root.MustWorkspaceClient + cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { + ctx := cmd.Context() + w := cmdctx.WorkspaceClient(ctx) + + getExternalServicePrincipalProxyReq.Name = args[0] + + response, err := w.WorkspaceIamV2.GetExternalServicePrincipalProxy(ctx, getExternalServicePrincipalProxyReq) + if err != nil { + return err + } + + return cmdio.Render(ctx, response) + } + + // Disable completions since they are not applicable. + // Can be overridden by manual implementation in `override.go`. + cmd.ValidArgsFunction = cobra.NoFileCompletions + + // Apply optional overrides to this command. + for _, fn := range getExternalServicePrincipalProxyOverrides { + fn(cmd, &getExternalServicePrincipalProxyReq) + } + + return cmd +} + +// start get-external-user-proxy command + +// Slice with functions to override default command behavior. +// Functions can be added from the `init()` function in manually curated files in this directory. +var getExternalUserProxyOverrides []func( + *cobra.Command, + *iamv2.GetExternalUserProxyRequest, +) + +func newGetExternalUserProxy() *cobra.Command { + cmd := &cobra.Command{} + + var getExternalUserProxyReq iamv2.GetExternalUserProxyRequest + + cmd.Use = "get-external-user-proxy NAME" + cmd.Short = `*Beta* Get an external user in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Get an external user in the account. + + Retrieves an external user with the given external ID from the customer's IdP. + If the user does not exist, it will be created. If the customer is not + onboarded onto Automatic Identity Management (AIM), this will return an error. + Workspace-scoped variant for workspace-authenticated callers. + + Arguments: + NAME: Required. The resource name of the external user. Format: + external-users/{external_user_id}` + + cmd.Annotations = make(map[string]string) + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" + + cmd.Args = func(cmd *cobra.Command, args []string) error { + check := root.ExactArgs(1) + return check(cmd, args) + } + + cmd.PreRunE = root.MustWorkspaceClient + cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { + ctx := cmd.Context() + w := cmdctx.WorkspaceClient(ctx) + + getExternalUserProxyReq.Name = args[0] + + response, err := w.WorkspaceIamV2.GetExternalUserProxy(ctx, getExternalUserProxyReq) + if err != nil { + return err + } + + return cmdio.Render(ctx, response) + } + + // Disable completions since they are not applicable. + // Can be overridden by manual implementation in `override.go`. + cmd.ValidArgsFunction = cobra.NoFileCompletions + + // Apply optional overrides to this command. + for _, fn := range getExternalUserProxyOverrides { + fn(cmd, &getExternalUserProxyReq) + } + + return cmd +} + // start get-group-proxy command // Slice with functions to override default command behavior. @@ -1160,8 +1345,10 @@ func newGetGroupProxy() *cobra.Command { var getGroupProxyReq iamv2.GetGroupProxyRequest cmd.Use = "get-group-proxy GROUP_ID" - cmd.Short = `Get a group in the account.` - cmd.Long = `Get a group in the account. + cmd.Short = `*Beta* Get a group in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Get a group in the account. Fetches a group by its internal ID from the Databricks account that parents the calling workspace. @@ -1169,12 +1356,9 @@ func newGetGroupProxy() *cobra.Command { Arguments: GROUP_ID: Required. Internal ID of the group in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -1223,8 +1407,10 @@ func newGetServicePrincipalProxy() *cobra.Command { var getServicePrincipalProxyReq iamv2.GetServicePrincipalProxyRequest cmd.Use = "get-service-principal-proxy SERVICE_PRINCIPAL_ID" - cmd.Short = `Get a service principal in the account.` - cmd.Long = `Get a service principal in the account. + cmd.Short = `*Beta* Get a service principal in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Get a service principal in the account. Fetches a service principal by its internal ID from the Databricks account that parents the calling workspace. @@ -1232,12 +1418,9 @@ func newGetServicePrincipalProxy() *cobra.Command { Arguments: SERVICE_PRINCIPAL_ID: Required. Internal ID of the service principal in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -1286,8 +1469,10 @@ func newGetUserProxy() *cobra.Command { var getUserProxyReq iamv2.GetUserProxyRequest cmd.Use = "get-user-proxy USER_ID" - cmd.Short = `Get a user in the account.` - cmd.Long = `Get a user in the account. + cmd.Short = `*Beta* Get a user in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Get a user in the account. Fetches a user by its internal ID from the Databricks account that parents the calling workspace. @@ -1295,12 +1480,9 @@ func newGetUserProxy() *cobra.Command { Arguments: USER_ID: Required. Internal ID of the user in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -1487,8 +1669,10 @@ func newGetWorkspaceAssignmentProxy() *cobra.Command { var getWorkspaceAssignmentProxyReq iamv2.GetWorkspaceAssignmentProxyRequest cmd.Use = "get-workspace-assignment-proxy PRINCIPAL_ID" - cmd.Short = `Get a workspace assignment for a principal.` - cmd.Long = `Get a workspace assignment for a principal. + cmd.Short = `*Beta* Get a workspace assignment for a principal.` + cmd.Long = `This command is in Beta and may change without notice. + +Get a workspace assignment for a principal. Returns the assignment for a principal in the calling workspace. @@ -1496,12 +1680,9 @@ func newGetWorkspaceAssignmentProxy() *cobra.Command { PRINCIPAL_ID: Required. The internal ID of the principal (user/sp/group) for which the assignment is being requested.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -1553,8 +1734,10 @@ func newGetWorkspaceIdentityDetail() *cobra.Command { var getWorkspaceIdentityDetailReq iamv2.GetWorkspaceIdentityDetailRequest cmd.Use = "get-workspace-identity-detail PRINCIPAL_ID" - cmd.Short = `Get workspace identity details for a principal.` - cmd.Long = `Get workspace identity details for a principal. + cmd.Short = `*Beta* Get workspace identity details for a principal.` + cmd.Long = `This command is in Beta and may change without notice. + +Get workspace identity details for a principal. Returns the identity details for a principal in a workspace. @@ -1562,12 +1745,9 @@ func newGetWorkspaceIdentityDetail() *cobra.Command { PRINCIPAL_ID: Required. The internal ID of the principal (user/sp/group) for which the identity details are being requested.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -1632,8 +1812,10 @@ func newListDirectGroupMembersProxy() *cobra.Command { cmd.Flags().Lookup("page-token").Hidden = true cmd.Use = "list-direct-group-members-proxy GROUP_ID" - cmd.Short = `List direct group members.` - cmd.Long = `List direct group members. + cmd.Short = `*Beta* List direct group members.` + cmd.Long = `This command is in Beta and may change without notice. + +List direct group members. Lists provisioned direct members of a group with their membership source (internal or from identity provider). @@ -1642,12 +1824,9 @@ func newListDirectGroupMembersProxy() *cobra.Command { GROUP_ID: Required. Internal ID of the group in Databricks whose direct members are being listed.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -1716,18 +1895,17 @@ func newListGroupsProxy() *cobra.Command { cmd.Flags().Lookup("page-token").Hidden = true cmd.Use = "list-groups-proxy" - cmd.Short = `List groups in the account.` - cmd.Long = `List groups in the account. + cmd.Short = `*Beta* List groups in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +List groups in the account. Lists the groups in the Databricks account that parents the calling workspace, returning one page per call. Supports filtering by group name or external ID.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(0) @@ -1791,19 +1969,18 @@ func newListServicePrincipalsProxy() *cobra.Command { cmd.Flags().Lookup("page-token").Hidden = true cmd.Use = "list-service-principals-proxy" - cmd.Short = `List service principals in the account.` - cmd.Long = `List service principals in the account. + cmd.Short = `*Beta* List service principals in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +List service principals in the account. Lists the service principals in the Databricks account that parents the calling workspace, returning one page per call. Supports filtering by application ID or external ID.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(0) @@ -1856,8 +2033,10 @@ func newListTransitiveParentGroupsProxy() *cobra.Command { cmd.Flags().StringVar(&listTransitiveParentGroupsProxyReq.PageToken, "page-token", listTransitiveParentGroupsProxyReq.PageToken, `A page token, received from a previous ListTransitiveParentGroups call.`) cmd.Use = "list-transitive-parent-groups-proxy PRINCIPAL_ID" - cmd.Short = `List all transitive parent groups of a principal.` - cmd.Long = `List all transitive parent groups of a principal. + cmd.Short = `*Beta* List all transitive parent groups of a principal.` + cmd.Long = `This command is in Beta and may change without notice. + +List all transitive parent groups of a principal. Lists all transitive parent groups of a principal. @@ -1865,12 +2044,9 @@ func newListTransitiveParentGroupsProxy() *cobra.Command { PRINCIPAL_ID: Required. Internal ID of the principal in Databricks whose transitive parent groups are being listed.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -1936,18 +2112,17 @@ func newListUsersProxy() *cobra.Command { cmd.Flags().Lookup("page-token").Hidden = true cmd.Use = "list-users-proxy" - cmd.Short = `List users in the account.` - cmd.Long = `List users in the account. + cmd.Short = `*Beta* List users in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +List users in the account. Lists the users in the Databricks account that parents the calling workspace, returning one page per call. Supports filtering by username or external ID.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(0) @@ -2086,20 +2261,19 @@ func newListWorkspaceAssignmentsProxy() *cobra.Command { cmd.Flags().Lookup("page-token").Hidden = true cmd.Use = "list-workspace-assignments-proxy" - cmd.Short = `List workspace assignments for a workspace.` - cmd.Long = `List workspace assignments for a workspace. + cmd.Short = `*Beta* List workspace assignments for a workspace.` + cmd.Long = `This command is in Beta and may change without notice. + +List workspace assignments for a workspace. Lists workspace assignments for the calling workspace. The response omits the per-principal entitlement fields (entitlements and effective_entitlements). To read the entitlements for a single principal, get that principal's assignment.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(0) @@ -2419,8 +2593,10 @@ func newUpdateGroupProxy() *cobra.Command { cmd.Flags().StringVar(&updateGroupProxyReq.Group.GroupName, "group-name", updateGroupProxyReq.Group.GroupName, `Display name of the group.`) cmd.Use = "update-group-proxy GROUP_ID UPDATE_MASK" - cmd.Short = `Update a group in the account.` - cmd.Long = `Update a group in the account. + cmd.Short = `*Beta* Update a group in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Update a group in the account. Updates an existing group in the Databricks account that parents the calling workspace. Only the fields named in the update mask are modified. Returns the @@ -2434,12 +2610,9 @@ func newUpdateGroupProxy() *cobra.Command { GROUP_ID: Required. Internal ID of the group in Databricks. UPDATE_MASK: Optional. The list of fields to update.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(2) @@ -2507,8 +2680,10 @@ func newUpdateServicePrincipalProxy() *cobra.Command { cmd.Flags().StringVar(&updateServicePrincipalProxyReq.ServicePrincipal.ExternalId, "external-id", updateServicePrincipalProxyReq.ServicePrincipal.ExternalId, `ExternalId of the service principal in the customer's IdP.`) cmd.Use = "update-service-principal-proxy SERVICE_PRINCIPAL_ID UPDATE_MASK DISPLAY_NAME ACCOUNT_SP_STATUS" - cmd.Short = `Update a service principal in the account.` - cmd.Long = `Update a service principal in the account. + cmd.Short = `*Beta* Update a service principal in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Update a service principal in the account. Updates an existing service principal in the Databricks account that parents the calling workspace. Only the fields named in the update mask are modified. @@ -2525,12 +2700,9 @@ func newUpdateServicePrincipalProxy() *cobra.Command { ACCOUNT_SP_STATUS: The activity status of a service principal in a Databricks account. Supported values: [ACTIVE, INACTIVE]` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("json") { @@ -2615,8 +2787,10 @@ func newUpdateUserProxy() *cobra.Command { cmd.Flags().StringVar(&updateUserProxyReq.User.ExternalId, "external-id", updateUserProxyReq.User.ExternalId, `ExternalId of the user in the customer's IdP.`) cmd.Use = "update-user-proxy USER_ID UPDATE_MASK USERNAME FULL_NAME ACCOUNT_USER_STATUS" - cmd.Short = `Update a user in the account.` - cmd.Long = `Update a user in the account. + cmd.Short = `*Beta* Update a user in the account.` + cmd.Long = `This command is in Beta and may change without notice. + +Update a user in the account. Updates an existing user in the Databricks account that parents the calling workspace and returns the updated user. Only the fields named in the update @@ -2635,12 +2809,9 @@ func newUpdateUserProxy() *cobra.Command { ACCOUNT_USER_STATUS: The activity status of a user in a Databricks account. Supported values: [ACTIVE, INACTIVE]` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("json") { @@ -2841,8 +3012,10 @@ func newUpdateWorkspaceAssignmentProxy() *cobra.Command { // TODO: array: entitlements cmd.Use = "update-workspace-assignment-proxy PRINCIPAL_ID UPDATE_MASK PRINCIPAL_ID" - cmd.Short = `Update a workspace assignment for a workspace.` - cmd.Long = `Update a workspace assignment for a workspace. + cmd.Short = `*Beta* Update a workspace assignment for a workspace.` + cmd.Long = `This command is in Beta and may change without notice. + +Update a workspace assignment for a workspace. Updates the entitlements of a directly assigned principal in the calling workspace. Changes are applied one at a time rather than atomically. If the @@ -2854,12 +3027,9 @@ func newUpdateWorkspaceAssignmentProxy() *cobra.Command { UPDATE_MASK: Required. The list of fields to update. PRINCIPAL_ID: The internal ID of the principal (user/sp/group) in Databricks.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("json") { @@ -2948,8 +3118,10 @@ func newUpdateWorkspaceIdentityDetail() *cobra.Command { cmd.Flags().Var(&updateWorkspaceIdentityDetailReq.WorkspaceIdentityDetail.WorkspaceIdentityStatus, "workspace-identity-status", `The activity status of an identity in a Databricks workspace. Supported values: [ACTIVE, INACTIVE]`) cmd.Use = "update-workspace-identity-detail PRINCIPAL_ID UPDATE_MASK" - cmd.Short = `Update workspace identity details for a principal.` - cmd.Long = `Update workspace identity details for a principal. + cmd.Short = `*Beta* Update workspace identity details for a principal.` + cmd.Long = `This command is in Beta and may change without notice. + +Update workspace identity details for a principal. Updates a workspace identity detail for a principal. @@ -2957,12 +3129,9 @@ func newUpdateWorkspaceIdentityDetail() *cobra.Command { PRINCIPAL_ID: Required. ID of the principal in Databricks. UPDATE_MASK: Required. The list of fields to update.` - // This command is being previewed; hide from help output. - cmd.Hidden = true - cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PRIVATE_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Private Preview" + cmd.Annotations["launch_stage"] = "PUBLIC_BETA" + cmd.Annotations["launch_stage_display"] = "Beta" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(2) diff --git a/cmd/workspace/workspace-settings-v2/workspace-settings-v2.go b/cmd/workspace/workspace-settings-v2/workspace-settings-v2.go index 9f3f722e1d9..c937b06bf9c 100644 --- a/cmd/workspace/workspace-settings-v2/workspace-settings-v2.go +++ b/cmd/workspace/workspace-settings-v2/workspace-settings-v2.go @@ -19,18 +19,16 @@ var cmdOverrides []func(*cobra.Command) func New() *cobra.Command { cmd := &cobra.Command{ - Use: "workspace-settings-v2", - Short: `*Public Preview* APIs to manage workspace level settings.`, - Long: `This command is in Public Preview and may change without notice. - -APIs to manage workspace level settings`, + Use: "workspace-settings-v2", + Short: `APIs to manage workspace level settings.`, + Long: `APIs to manage workspace level settings`, GroupID: "settings", RunE: root.ReportUnknownSubcommand, } cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PUBLIC_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Public Preview" + cmd.Annotations["launch_stage"] = "GA" + cmd.Annotations["launch_stage_display"] = "GA" // Add methods cmd.AddCommand(newGetPublicWorkspaceSetting()) @@ -60,10 +58,8 @@ func newGetPublicWorkspaceSetting() *cobra.Command { var getPublicWorkspaceSettingReq settingsv2.GetPublicWorkspaceSettingRequest cmd.Use = "get-public-workspace-setting NAME" - cmd.Short = `*Public Preview* Get a workspace setting.` - cmd.Long = `This command is in Public Preview and may change without notice. - -Get a workspace setting. + cmd.Short = `Get a workspace setting.` + cmd.Long = `Get a workspace setting. Get a setting value at workspace level. See :method:settingsv2/listworkspacesettingsmetadata for list of setting available @@ -73,8 +69,8 @@ Get a workspace setting. NAME: Name of the setting` cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PUBLIC_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Public Preview" + cmd.Annotations["launch_stage"] = "GA" + cmd.Annotations["launch_stage_display"] = "GA" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) @@ -136,18 +132,16 @@ func newListWorkspaceSettingsMetadata() *cobra.Command { cmd.Flags().Lookup("page-token").Hidden = true cmd.Use = "list-workspace-settings-metadata" - cmd.Short = `*Public Preview* List valid setting keys and their metadata.` - cmd.Long = `This command is in Public Preview and may change without notice. - -List valid setting keys and their metadata. + cmd.Short = `List valid setting keys and their metadata.` + cmd.Long = `List valid setting keys and their metadata. List valid setting keys and metadata. These settings are available to be referenced via GET :method:settingsv2/getpublicworkspacesetting and PATCH :method:settingsv2/patchpublicworkspacesetting APIs` cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PUBLIC_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Public Preview" + cmd.Annotations["launch_stage"] = "GA" + cmd.Annotations["launch_stage_display"] = "GA" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(0) @@ -225,10 +219,8 @@ func newPatchPublicWorkspaceSetting() *cobra.Command { // TODO: complex arg: string_val cmd.Use = "patch-public-workspace-setting NAME" - cmd.Short = `*Public Preview* Update a workspace setting.` - cmd.Long = `This command is in Public Preview and may change without notice. - -Update a workspace setting. + cmd.Short = `Update a workspace setting.` + cmd.Long = `Update a workspace setting. Patch a setting value at workspace level. See :method:settingsv2/listworkspacesettingsmetadata for list of setting available @@ -242,8 +234,8 @@ Update a workspace setting. NAME: Name of the setting` cmd.Annotations = make(map[string]string) - cmd.Annotations["launch_stage"] = "PUBLIC_PREVIEW" - cmd.Annotations["launch_stage_display"] = "Public Preview" + cmd.Annotations["launch_stage"] = "GA" + cmd.Annotations["launch_stage_display"] = "GA" cmd.Args = func(cmd *cobra.Command, args []string) error { check := root.ExactArgs(1) diff --git a/go.mod b/go.mod index 8cf427d951d..60408085fe8 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/charmbracelet/huh v1.0.0 // MIT github.com/charmbracelet/lipgloss v1.1.0 // MIT github.com/charmbracelet/x/ansi v0.11.7 // MIT - github.com/databricks/databricks-sdk-go v0.175.0 // Apache-2.0 + github.com/databricks/databricks-sdk-go v0.177.0 // Apache-2.0 github.com/google/jsonschema-go v0.4.3 // MIT github.com/google/uuid v1.6.0 // BSD-3-Clause github.com/gorilla/websocket v1.5.3 // BSD-2-Clause diff --git a/go.sum b/go.sum index 9929dd6cc48..14991356bf8 100644 --- a/go.sum +++ b/go.sum @@ -69,8 +69,8 @@ github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22r github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/danieljoos/wincred v1.2.3 h1:v7dZC2x32Ut3nEfRH+vhoZGvN72+dQ/snVXo/vMFLdQ= github.com/danieljoos/wincred v1.2.3/go.mod h1:6qqX0WNrS4RzPZ1tnroDzq9kY3fu1KwE7MRLQK4X0bs= -github.com/databricks/databricks-sdk-go v0.175.0 h1:XJKS5dqV23fADlEgo/PTYo74+lhzR8sUXJZv8qoNr50= -github.com/databricks/databricks-sdk-go v0.175.0/go.mod h1:udBw6nxkaqa0fgPQ7ZW1kGFkltQncYx+qFJeVFmxtz8= +github.com/databricks/databricks-sdk-go v0.177.0 h1:RGSGHjJEzS5aat2mr7MMnWZPovjUG+XwtAeDjpl0ET8= +github.com/databricks/databricks-sdk-go v0.177.0/go.mod h1:udBw6nxkaqa0fgPQ7ZW1kGFkltQncYx+qFJeVFmxtz8= github.com/databricks/sdk-go/auth v0.0.0-dev h1:SyRGZvExH5TG9ynZEqNn+m+xTY42VOXr2GOxgNOQexk= github.com/databricks/sdk-go/auth v0.0.0-dev/go.mod h1:Tj09W13MScUaix94cR0He9msAwe40JAQKuS2jP/ofQA= github.com/databricks/sdk-go/core v0.0.1-dev h1:sIA1hCEJyl8/012vOBUIkDjsycNCD8RwfP76SCM0QbQ= diff --git a/python/databricks/bundles/alerts/_models/alert.py b/python/databricks/bundles/alerts/_models/alert.py index d99784a4e17..8df0acdc6aa 100644 --- a/python/databricks/bundles/alerts/_models/alert.py +++ b/python/databricks/bundles/alerts/_models/alert.py @@ -78,8 +78,17 @@ class Alert(Resource): """ :meta private: [EXPERIMENTAL] - [Private Preview] Query parameters bound when executing the alert query, referenced in the - query text with `:name` syntax. Static values only. + [Private Preview] A list of parameters to pass into the alert SQL query statement containing parameter markers. Static values only. + + Reference a parameter in the query text as `:name`. Each parameter must have a unique, non-empty name. + Each parameter consists of a name, a value, and optionally a type. To represent a NULL + value, the `value` field may be omitted or set to `null` explicitly. If the `type` field + is omitted, the value is interpreted as a string. + + If the type is given, parameters will be checked for type correctness according + to the given type. A value is correct if the provided string can be converted to + the requested type using the `cast` function. The exact semantics are described in + the section [`cast` function](https://docs.databricks.com/sql/language-manual/functions/cast.html) of the SQL language reference. """ parent_path: VariableOrOptional[str] = None @@ -159,8 +168,17 @@ class AlertDict(TypedDict, total=False): """ :meta private: [EXPERIMENTAL] - [Private Preview] Query parameters bound when executing the alert query, referenced in the - query text with `:name` syntax. Static values only. + [Private Preview] A list of parameters to pass into the alert SQL query statement containing parameter markers. Static values only. + + Reference a parameter in the query text as `:name`. Each parameter must have a unique, non-empty name. + Each parameter consists of a name, a value, and optionally a type. To represent a NULL + value, the `value` field may be omitted or set to `null` explicitly. If the `type` field + is omitted, the value is interpreted as a string. + + If the type is given, parameters will be checked for type correctness according + to the given type. A value is correct if the provided string can be converted to + the requested type using the `cast` function. The exact semantics are described in + the section [`cast` function](https://docs.databricks.com/sql/language-manual/functions/cast.html) of the SQL language reference. """ parent_path: VariableOrOptional[str] diff --git a/python/databricks/bundles/alerts/_models/alert_statement_parameter.py b/python/databricks/bundles/alerts/_models/alert_statement_parameter.py index 22d4571f08f..def206d148d 100644 --- a/python/databricks/bundles/alerts/_models/alert_statement_parameter.py +++ b/python/databricks/bundles/alerts/_models/alert_statement_parameter.py @@ -16,34 +16,31 @@ class AlertStatementParameter: """ :meta private: [EXPERIMENTAL] - Redash-owned copy of the internal StatementParameter for the external AlertV2 API. - The internal `ordinal` and `args` fields are intentionally omitted: the public API - supports only flat, named scalar parameters; complex types (ARRAY, MAP, STRUCT) are - not supported. This mirrors SEA's public StatementParameter schema, see: - cmdexec/sql-exec-api/proto/sql_exec_api_service.proto:763-779 + A named parameter bound to the alert query. Only flat, named scalar parameters are + supported; complex types such as ARRAY, MAP, and STRUCT are not. """ name: VariableOr[str] """ :meta private: [EXPERIMENTAL] - [Private Preview] The name of the parameter, referenced in the query as `:name`. + [Private Preview] The name of the parameter. Reference it in the query text as `:name`. Required, must be + non-empty, and must be unique across the alert's parameters. """ type: VariableOrOptional[str] = None """ :meta private: [EXPERIMENTAL] - [Private Preview] The SQL data type of the parameter, e.g. STRING, INT, or DATE. Defaults to STRING. This is a - string rather than an enum because scalar subtypes such as DECIMAL(10, 4) cannot be enumerated. - Complex types such as ARRAY, MAP, and STRUCT are not supported. + [Private Preview] The SQL data type of the parameter, for example `STRING`, `INT`, or `DECIMAL(10, 2)`. If no type is given + the type is assumed to be `STRING`. Complex types such as `ARRAY`, `MAP`, and `STRUCT` are not supported. """ value: VariableOrOptional[str] = None """ :meta private: [EXPERIMENTAL] - [Private Preview] The bound value for the parameter, given as a string. If omitted, the value is interpreted as NULL. + [Private Preview] The value bound to the parameter, represented as a string. If omitted, the value is interpreted as NULL. """ @classmethod @@ -61,23 +58,23 @@ class AlertStatementParameterDict(TypedDict, total=False): """ :meta private: [EXPERIMENTAL] - [Private Preview] The name of the parameter, referenced in the query as `:name`. + [Private Preview] The name of the parameter. Reference it in the query text as `:name`. Required, must be + non-empty, and must be unique across the alert's parameters. """ type: VariableOrOptional[str] """ :meta private: [EXPERIMENTAL] - [Private Preview] The SQL data type of the parameter, e.g. STRING, INT, or DATE. Defaults to STRING. This is a - string rather than an enum because scalar subtypes such as DECIMAL(10, 4) cannot be enumerated. - Complex types such as ARRAY, MAP, and STRUCT are not supported. + [Private Preview] The SQL data type of the parameter, for example `STRING`, `INT`, or `DECIMAL(10, 2)`. If no type is given + the type is assumed to be `STRING`. Complex types such as `ARRAY`, `MAP`, and `STRUCT` are not supported. """ value: VariableOrOptional[str] """ :meta private: [EXPERIMENTAL] - [Private Preview] The bound value for the parameter, given as a string. If omitted, the value is interpreted as NULL. + [Private Preview] The value bound to the parameter, represented as a string. If omitted, the value is interpreted as NULL. """ diff --git a/python/databricks/bundles/jobs/__init__.py b/python/databricks/bundles/jobs/__init__.py index 3e775fcb16c..9aeaa9dd327 100644 --- a/python/databricks/bundles/jobs/__init__.py +++ b/python/databricks/bundles/jobs/__init__.py @@ -77,6 +77,8 @@ "DashboardTaskParam", "DataSecurityMode", "DataSecurityModeParam", + "DayOfWeek", + "DayOfWeekParam", "DbfsStorageInfo", "DbfsStorageInfoDict", "DbfsStorageInfoParam", @@ -179,6 +181,9 @@ "LogAnalyticsInfo", "LogAnalyticsInfoDict", "LogAnalyticsInfoParam", + "MaintenanceWindow", + "MaintenanceWindowDict", + "MaintenanceWindowParam", "MavenLibrary", "MavenLibraryDict", "MavenLibraryParam", @@ -456,6 +461,7 @@ DataSecurityMode, DataSecurityModeParam, ) +from databricks.bundles.jobs._models.day_of_week import DayOfWeek, DayOfWeekParam from databricks.bundles.jobs._models.dbfs_storage_info import ( DbfsStorageInfo, DbfsStorageInfoDict, @@ -614,6 +620,11 @@ LogAnalyticsInfoDict, LogAnalyticsInfoParam, ) +from databricks.bundles.jobs._models.maintenance_window import ( + MaintenanceWindow, + MaintenanceWindowDict, + MaintenanceWindowParam, +) from databricks.bundles.jobs._models.maven_library import ( MavenLibrary, MavenLibraryDict, diff --git a/python/databricks/bundles/jobs/_models/alert_task.py b/python/databricks/bundles/jobs/_models/alert_task.py index 9060a9b96df..4f3b0d97611 100644 --- a/python/databricks/bundles/jobs/_models/alert_task.py +++ b/python/databricks/bundles/jobs/_models/alert_task.py @@ -5,7 +5,11 @@ from databricks.bundles.core._transform import _transform from databricks.bundles.core._transform_to_json import _transform_to_json_value -from databricks.bundles.core._variable import VariableOrList, VariableOrOptional +from databricks.bundles.core._variable import ( + VariableOrDict, + VariableOrList, + VariableOrOptional, +) from databricks.bundles.jobs._models.alert_task_subscriber import ( AlertTaskSubscriber, AlertTaskSubscriberParam, @@ -24,6 +28,18 @@ class AlertTask: [Public Preview] The alert_id is the canonical identifier of the alert. """ + parameters: VariableOrDict[str] = field(default_factory=dict) + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] Per-run parameter overrides, keyed by parameter name, applied onto the alert's stored + query parameters before the query is executed. Only scalar values are supported. Values + may reference job parameters with `{{job.parameters.*}}`, which are resolved before the + task runs. An override whose key does not match a stored parameter fails the task run. + Limited to 10000 characters when serialized as JSON; keys must be 1-100 characters and + contain only letters, digits, underscores, dashes, and periods. + """ + subscribers: VariableOrList[AlertTaskSubscriber] = field(default_factory=list) """ [Public Preview] The subscribers receive alert evaluation result notifications after the alert task is completed. @@ -59,6 +75,18 @@ class AlertTaskDict(TypedDict, total=False): [Public Preview] The alert_id is the canonical identifier of the alert. """ + parameters: VariableOrDict[str] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] Per-run parameter overrides, keyed by parameter name, applied onto the alert's stored + query parameters before the query is executed. Only scalar values are supported. Values + may reference job parameters with `{{job.parameters.*}}`, which are resolved before the + task runs. An override whose key does not match a stored parameter fails the task run. + Limited to 10000 characters when serialized as JSON; keys must be 1-100 characters and + contain only letters, digits, underscores, dashes, and periods. + """ + subscribers: VariableOrList[AlertTaskSubscriberParam] """ [Public Preview] The subscribers receive alert evaluation result notifications after the alert task is completed. diff --git a/python/databricks/bundles/jobs/_models/cluster_spec.py b/python/databricks/bundles/jobs/_models/cluster_spec.py index 685863137f3..6a412571a29 100644 --- a/python/databricks/bundles/jobs/_models/cluster_spec.py +++ b/python/databricks/bundles/jobs/_models/cluster_spec.py @@ -312,7 +312,7 @@ class ClusterSpec: total_initial_remote_disk_size: VariableOrOptional[int] = None """ - If set, what the total initial volume size (in GB) of the remote disks should be. Currently only supported for GCP HYPERDISK_BALANCED disks. + If set, what the total initial volume size (in GB) of the remote disks should be. Supported for GCP. """ use_ml_runtime: VariableOrOptional[bool] = None @@ -588,7 +588,7 @@ class ClusterSpecDict(TypedDict, total=False): total_initial_remote_disk_size: VariableOrOptional[int] """ - If set, what the total initial volume size (in GB) of the remote disks should be. Currently only supported for GCP HYPERDISK_BALANCED disks. + If set, what the total initial volume size (in GB) of the remote disks should be. Supported for GCP. """ use_ml_runtime: VariableOrOptional[bool] diff --git a/python/databricks/bundles/jobs/_models/continuous.py b/python/databricks/bundles/jobs/_models/continuous.py index 805c7e1d654..a5877e0790d 100644 --- a/python/databricks/bundles/jobs/_models/continuous.py +++ b/python/databricks/bundles/jobs/_models/continuous.py @@ -6,6 +6,10 @@ from databricks.bundles.core._transform import _transform from databricks.bundles.core._transform_to_json import _transform_to_json_value from databricks.bundles.core._variable import VariableOrOptional +from databricks.bundles.jobs._models.maintenance_window import ( + MaintenanceWindow, + MaintenanceWindowParam, +) from databricks.bundles.jobs._models.pause_status import PauseStatus, PauseStatusParam from databricks.bundles.jobs._models.task_retry_mode import ( TaskRetryMode, @@ -20,6 +24,13 @@ class Continuous: """""" + maintenance_window: VariableOrOptional[MaintenanceWindow] = None + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] Defines when platform-initiated maintenance may run for this job. If unspecified, maintenance may run at any time. + """ + pause_status: VariableOrOptional[PauseStatus] = None """ Indicate whether the continuous execution of the job is paused or not. Defaults to UNPAUSED. @@ -41,6 +52,13 @@ def as_dict(self) -> "ContinuousDict": class ContinuousDict(TypedDict, total=False): """""" + maintenance_window: VariableOrOptional[MaintenanceWindowParam] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] Defines when platform-initiated maintenance may run for this job. If unspecified, maintenance may run at any time. + """ + pause_status: VariableOrOptional[PauseStatusParam] """ Indicate whether the continuous execution of the job is paused or not. Defaults to UNPAUSED. diff --git a/python/databricks/bundles/jobs/_models/continuous_trigger_configuration.py b/python/databricks/bundles/jobs/_models/continuous_trigger_configuration.py index 866ffda4c61..e8667994d27 100644 --- a/python/databricks/bundles/jobs/_models/continuous_trigger_configuration.py +++ b/python/databricks/bundles/jobs/_models/continuous_trigger_configuration.py @@ -6,6 +6,10 @@ from databricks.bundles.core._transform import _transform from databricks.bundles.core._transform_to_json import _transform_to_json_value from databricks.bundles.core._variable import VariableOrOptional +from databricks.bundles.jobs._models.maintenance_window import ( + MaintenanceWindow, + MaintenanceWindowParam, +) from databricks.bundles.jobs._models.task_retry_mode import ( TaskRetryMode, TaskRetryModeParam, @@ -22,6 +26,14 @@ class ContinuousTriggerConfiguration: `TriggerConfiguration` and intentionally omitted here. """ + maintenance_window: VariableOrOptional[MaintenanceWindow] = None + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] Defines when platform-initiated maintenance may run for this trigger. If unspecified, + maintenance may run at any time. + """ + task_retry_mode: VariableOrOptional[TaskRetryMode] = None """ [Beta] Whether the continuous job applies task-level retries. Defaults to NEVER. @@ -38,6 +50,14 @@ def as_dict(self) -> "ContinuousTriggerConfigurationDict": class ContinuousTriggerConfigurationDict(TypedDict, total=False): """""" + maintenance_window: VariableOrOptional[MaintenanceWindowParam] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] Defines when platform-initiated maintenance may run for this trigger. If unspecified, + maintenance may run at any time. + """ + task_retry_mode: VariableOrOptional[TaskRetryModeParam] """ [Beta] Whether the continuous job applies task-level retries. Defaults to NEVER. diff --git a/python/databricks/bundles/jobs/_models/dashboard_task.py b/python/databricks/bundles/jobs/_models/dashboard_task.py index abc9005172f..94ae8f645f1 100644 --- a/python/databricks/bundles/jobs/_models/dashboard_task.py +++ b/python/databricks/bundles/jobs/_models/dashboard_task.py @@ -6,7 +6,10 @@ from databricks.bundles.core._transform import _transform from databricks.bundles.core._transform_to_json import _transform_to_json_value from databricks.bundles.core._variable import VariableOrDict, VariableOrOptional -from databricks.bundles.jobs._models.subscription import Subscription, SubscriptionParam +from databricks.bundles.jobs._models.subscription import ( + Subscription, + SubscriptionParam, +) if TYPE_CHECKING: from typing_extensions import Self diff --git a/python/databricks/bundles/jobs/_models/day_of_week.py b/python/databricks/bundles/jobs/_models/day_of_week.py new file mode 100644 index 00000000000..19abc1c56a2 --- /dev/null +++ b/python/databricks/bundles/jobs/_models/day_of_week.py @@ -0,0 +1,28 @@ +# Code generated by pydabs-codegen. DO NOT EDIT. + +from enum import Enum +from typing import Literal + + +class DayOfWeek(Enum): + """ + :meta private: [EXPERIMENTAL] + + Days of week that can be referenced by Jobs scheduling settings. + """ + + MONDAY = "MONDAY" + TUESDAY = "TUESDAY" + WEDNESDAY = "WEDNESDAY" + THURSDAY = "THURSDAY" + FRIDAY = "FRIDAY" + SATURDAY = "SATURDAY" + SUNDAY = "SUNDAY" + + +DayOfWeekParam = ( + Literal[ + "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY" + ] + | DayOfWeek +) diff --git a/python/databricks/bundles/jobs/_models/hardware_accelerator_type.py b/python/databricks/bundles/jobs/_models/hardware_accelerator_type.py index 4b1501f0f25..8d3566aa66f 100644 --- a/python/databricks/bundles/jobs/_models/hardware_accelerator_type.py +++ b/python/databricks/bundles/jobs/_models/hardware_accelerator_type.py @@ -13,8 +13,9 @@ class HardwareAcceleratorType(Enum): GPU_1X_A10 = "GPU_1xA10" GPU_8X_H100 = "GPU_8xH100" + GPU_1X_H100 = "GPU_1xH100" HardwareAcceleratorTypeParam = ( - Literal["GPU_1xA10", "GPU_8xH100"] | HardwareAcceleratorType + Literal["GPU_1xA10", "GPU_8xH100", "GPU_1xH100"] | HardwareAcceleratorType ) diff --git a/python/databricks/bundles/jobs/_models/job.py b/python/databricks/bundles/jobs/_models/job.py index d4010ac38f8..929af07fcdf 100644 --- a/python/databricks/bundles/jobs/_models/job.py +++ b/python/databricks/bundles/jobs/_models/job.py @@ -87,6 +87,8 @@ class Job(Resource): continuous: VariableOrOptional[Continuous] = None """ An optional continuous property for this job. The continuous property will ensure that there is always one run executing. Only one of `schedule` and `continuous` can be used. + + Pipelines started by a continuous job also run continuously, regardless of their own pipeline mode setting. """ description: VariableOrOptional[str] = None @@ -256,6 +258,8 @@ class JobDict(TypedDict, total=False): continuous: VariableOrOptional[ContinuousParam] """ An optional continuous property for this job. The continuous property will ensure that there is always one run executing. Only one of `schedule` and `continuous` can be used. + + Pipelines started by a continuous job also run continuously, regardless of their own pipeline mode setting. """ description: VariableOrOptional[str] diff --git a/python/databricks/bundles/jobs/_models/maintenance_window.py b/python/databricks/bundles/jobs/_models/maintenance_window.py new file mode 100644 index 00000000000..12ba928c905 --- /dev/null +++ b/python/databricks/bundles/jobs/_models/maintenance_window.py @@ -0,0 +1,82 @@ +# Code generated by pydabs-codegen. DO NOT EDIT. + +from dataclasses import dataclass +from typing import TYPE_CHECKING, TypedDict + +from databricks.bundles.core._transform import _transform +from databricks.bundles.core._transform_to_json import _transform_to_json_value +from databricks.bundles.core._variable import VariableOr +from databricks.bundles.jobs._models.day_of_week import DayOfWeek, DayOfWeekParam + +if TYPE_CHECKING: + from typing_extensions import Self + + +@dataclass(kw_only=True) +class MaintenanceWindow: + """ + :meta private: [EXPERIMENTAL] + + A recurring weekly time window during which platform-initiated maintenance is + allowed to run for a continuous job. + """ + + day_of_week: VariableOr[DayOfWeek] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] The day of week on which maintenance is allowed to happen. This field is required. + """ + + start_hour: VariableOr[int] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] An integer between 0 and 23 denoting the start hour for the maintenance window in the 24-hour day. + Platform-initiated maintenance is triggered only within a one-hour window starting at this hour. + This field is required. + """ + + timezone_id: VariableOr[str] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] A Java timezone ID. The maintenance window is resolved with respect to this timezone. See [Java TimeZone](https://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html) for details. This field is required. + """ + + @classmethod + def from_dict(cls, value: "MaintenanceWindowDict") -> "Self": + return _transform(cls, value) + + def as_dict(self) -> "MaintenanceWindowDict": + return _transform_to_json_value(self) # type:ignore + + +class MaintenanceWindowDict(TypedDict, total=False): + """""" + + day_of_week: VariableOr[DayOfWeekParam] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] The day of week on which maintenance is allowed to happen. This field is required. + """ + + start_hour: VariableOr[int] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] An integer between 0 and 23 denoting the start hour for the maintenance window in the 24-hour day. + Platform-initiated maintenance is triggered only within a one-hour window starting at this hour. + This field is required. + """ + + timezone_id: VariableOr[str] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] A Java timezone ID. The maintenance window is resolved with respect to this timezone. See [Java TimeZone](https://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html) for details. This field is required. + """ + + +MaintenanceWindowParam = MaintenanceWindowDict | MaintenanceWindow diff --git a/python/databricks/bundles/jobs/_models/node_type_flexibility.py b/python/databricks/bundles/jobs/_models/node_type_flexibility.py index aa582b763a8..418ea9337bd 100644 --- a/python/databricks/bundles/jobs/_models/node_type_flexibility.py +++ b/python/databricks/bundles/jobs/_models/node_type_flexibility.py @@ -5,7 +5,7 @@ from databricks.bundles.core._transform import _transform from databricks.bundles.core._transform_to_json import _transform_to_json_value -from databricks.bundles.core._variable import VariableOrList +from databricks.bundles.core._variable import VariableOrList, VariableOrOptional if TYPE_CHECKING: from typing_extensions import Self @@ -22,6 +22,12 @@ class NodeTypeFlexibility: A list of node type IDs to use as fallbacks when the primary node type is unavailable. """ + aws_context_id: VariableOrOptional[str] = None + """ + The AWS Context ID for EC2 Fleet. + When set (non-empty), the value is passed to AWS CreateFleet API to create the EC2 Fleet. + """ + @classmethod def from_dict(cls, value: "NodeTypeFlexibilityDict") -> "Self": return _transform(cls, value) @@ -38,5 +44,11 @@ class NodeTypeFlexibilityDict(TypedDict, total=False): A list of node type IDs to use as fallbacks when the primary node type is unavailable. """ + aws_context_id: VariableOrOptional[str] + """ + The AWS Context ID for EC2 Fleet. + When set (non-empty), the value is passed to AWS CreateFleet API to create the EC2 Fleet. + """ + NodeTypeFlexibilityParam = NodeTypeFlexibilityDict | NodeTypeFlexibility diff --git a/python/databricks/bundles/jobs/_models/trigger_configuration.py b/python/databricks/bundles/jobs/_models/trigger_configuration.py index 259c45c7f9d..1437eb582ca 100644 --- a/python/databricks/bundles/jobs/_models/trigger_configuration.py +++ b/python/databricks/bundles/jobs/_models/trigger_configuration.py @@ -44,9 +44,9 @@ class TriggerConfiguration: """ A single trigger attached to a job via `JobSettings.triggers`. Exactly one of the trigger-type fields - (`periodic`, `schedule`, `continuous`, `file_arrival`, `table_update`, `model`) must be set; mutual exclusivity - is enforced in the API handler rather than via `oneof` so that codegen, validation, and JSON serialization - across SDKs and Terraform behave consistently. + (`periodic`, `schedule`, `continuous`, `file_arrival`, `table_update`, `model`, `job_completion`) must be set; + mutual exclusivity is enforced in the API handler rather than via `oneof` so that codegen, validation, and JSON + serialization across SDKs and Terraform behave consistently. """ continuous: VariableOrOptional[ContinuousTriggerConfiguration] = None diff --git a/python/databricks/bundles/pipelines/__init__.py b/python/databricks/bundles/pipelines/__init__.py index c3cdbee96f7..2d1adefe33d 100644 --- a/python/databricks/bundles/pipelines/__init__.py +++ b/python/databricks/bundles/pipelines/__init__.py @@ -200,6 +200,9 @@ "PostgresSlotConfig", "PostgresSlotConfigDict", "PostgresSlotConfigParam", + "RabbitmqOptions", + "RabbitmqOptionsDict", + "RabbitmqOptionsParam", "RedditAdsOptions", "RedditAdsOptionsDict", "RedditAdsOptionsParam", @@ -610,6 +613,11 @@ PostgresSlotConfigDict, PostgresSlotConfigParam, ) +from databricks.bundles.pipelines._models.rabbitmq_options import ( + RabbitmqOptions, + RabbitmqOptionsDict, + RabbitmqOptionsParam, +) from databricks.bundles.pipelines._models.reddit_ads_options import ( RedditAdsOptions, RedditAdsOptionsDict, diff --git a/python/databricks/bundles/pipelines/_models/connector_options.py b/python/databricks/bundles/pipelines/_models/connector_options.py index 5fc9bfce6cc..a55a4e86fcd 100644 --- a/python/databricks/bundles/pipelines/_models/connector_options.py +++ b/python/databricks/bundles/pipelines/_models/connector_options.py @@ -46,6 +46,10 @@ OutlookOptions, OutlookOptionsParam, ) +from databricks.bundles.pipelines._models.rabbitmq_options import ( + RabbitmqOptions, + RabbitmqOptionsParam, +) from databricks.bundles.pipelines._models.reddit_ads_options import ( RedditAdsOptions, RedditAdsOptionsParam, @@ -144,6 +148,14 @@ class ConnectorOptions: [Private Preview] Outlook specific options for ingestion """ + rabbitmq_options: VariableOrOptional[RabbitmqOptions] = None + """ + [Beta] RabbitMQ specific options for ingestion. + Performance tuning options (consumers_per_task, max_messages_per_fetch, etc.) + are intentionally not exposed in the public API. The managed connector uses + sensible defaults internally. These can be added later if user demand arises. + """ + reddit_ads_options: VariableOrOptional[RedditAdsOptions] = None """ :meta private: [EXPERIMENTAL] @@ -255,6 +267,14 @@ class ConnectorOptionsDict(TypedDict, total=False): [Private Preview] Outlook specific options for ingestion """ + rabbitmq_options: VariableOrOptional[RabbitmqOptionsParam] + """ + [Beta] RabbitMQ specific options for ingestion. + Performance tuning options (consumers_per_task, max_messages_per_fetch, etc.) + are intentionally not exposed in the public API. The managed connector uses + sensible defaults internally. These can be added later if user demand arises. + """ + reddit_ads_options: VariableOrOptional[RedditAdsOptionsParam] """ :meta private: [EXPERIMENTAL] diff --git a/python/databricks/bundles/pipelines/_models/ingestion_config.py b/python/databricks/bundles/pipelines/_models/ingestion_config.py index d301a71fb87..218711df402 100644 --- a/python/databricks/bundles/pipelines/_models/ingestion_config.py +++ b/python/databricks/bundles/pipelines/_models/ingestion_config.py @@ -6,7 +6,10 @@ from databricks.bundles.core._transform import _transform from databricks.bundles.core._transform_to_json import _transform_to_json_value from databricks.bundles.core._variable import VariableOrOptional -from databricks.bundles.pipelines._models.report_spec import ReportSpec, ReportSpecParam +from databricks.bundles.pipelines._models.report_spec import ( + ReportSpec, + ReportSpecParam, +) from databricks.bundles.pipelines._models.schema_spec import SchemaSpec, SchemaSpecParam from databricks.bundles.pipelines._models.table_spec import TableSpec, TableSpecParam diff --git a/python/databricks/bundles/pipelines/_models/pipeline.py b/python/databricks/bundles/pipelines/_models/pipeline.py index 9f179f7c7a9..69ac527cd70 100644 --- a/python/databricks/bundles/pipelines/_models/pipeline.py +++ b/python/databricks/bundles/pipelines/_models/pipeline.py @@ -102,7 +102,11 @@ class Pipeline(Resource): continuous: VariableOrOptional[bool] = None """ - Whether the pipeline is continuous or triggered. This replaces `trigger`. + [DEPRECATED] Whether the pipeline is continuous or triggered. This replaces `trigger`. + + Deprecated: wrap the pipeline in a continuous job instead, which also lets you take advantage + of job-level settings such as performance mode. When the pipeline is started by a continuous + job, the job's setting takes precedence and this field is ignored. """ development: VariableOrOptional[bool] = None @@ -293,7 +297,11 @@ class PipelineDict(TypedDict, total=False): continuous: VariableOrOptional[bool] """ - Whether the pipeline is continuous or triggered. This replaces `trigger`. + [DEPRECATED] Whether the pipeline is continuous or triggered. This replaces `trigger`. + + Deprecated: wrap the pipeline in a continuous job instead, which also lets you take advantage + of job-level settings such as performance mode. When the pipeline is started by a continuous + job, the job's setting takes precedence and this field is ignored. """ development: VariableOrOptional[bool] diff --git a/python/databricks/bundles/pipelines/_models/pipeline_cluster.py b/python/databricks/bundles/pipelines/_models/pipeline_cluster.py index 6261e74e5da..6eda9e865a0 100644 --- a/python/databricks/bundles/pipelines/_models/pipeline_cluster.py +++ b/python/databricks/bundles/pipelines/_models/pipeline_cluster.py @@ -122,7 +122,7 @@ class PipelineCluster: label: VariableOrOptional[str] = None """ - A label for the cluster specification, either `default` to configure the default cluster, or `maintenance` to configure the maintenance cluster. This field is optional. The default value is `default`. + A label for the cluster specification, either `default` to configure the default cluster settings applied to both the update and maintenance clusters, `updates` to configure the update cluster, or `maintenance` to configure the maintenance cluster. This field is optional. The default value is `default`. """ node_type_id: VariableOrOptional[str] = None @@ -268,7 +268,7 @@ class PipelineClusterDict(TypedDict, total=False): label: VariableOrOptional[str] """ - A label for the cluster specification, either `default` to configure the default cluster, or `maintenance` to configure the maintenance cluster. This field is optional. The default value is `default`. + A label for the cluster specification, either `default` to configure the default cluster settings applied to both the update and maintenance clusters, `updates` to configure the update cluster, or `maintenance` to configure the maintenance cluster. This field is optional. The default value is `default`. """ node_type_id: VariableOrOptional[str] diff --git a/python/databricks/bundles/pipelines/_models/pipelines_environment.py b/python/databricks/bundles/pipelines/_models/pipelines_environment.py index 095104bf8a2..0493c5d4fa7 100644 --- a/python/databricks/bundles/pipelines/_models/pipelines_environment.py +++ b/python/databricks/bundles/pipelines/_models/pipelines_environment.py @@ -27,7 +27,7 @@ class PipelinesEnvironment: environment_version: VariableOrOptional[str] = None """ - [Beta] The environment version of the serverless Python environment used to execute + [Public Preview] The environment version of the serverless Python environment used to execute customer Python code. Each environment version includes a specific Python version and a curated set of pre-installed libraries with defined versions, providing a stable and reproducible execution environment. @@ -59,7 +59,7 @@ class PipelinesEnvironmentDict(TypedDict, total=False): environment_version: VariableOrOptional[str] """ - [Beta] The environment version of the serverless Python environment used to execute + [Public Preview] The environment version of the serverless Python environment used to execute customer Python code. Each environment version includes a specific Python version and a curated set of pre-installed libraries with defined versions, providing a stable and reproducible execution environment. diff --git a/python/databricks/bundles/pipelines/_models/rabbitmq_options.py b/python/databricks/bundles/pipelines/_models/rabbitmq_options.py new file mode 100644 index 00000000000..cd78ee534f3 --- /dev/null +++ b/python/databricks/bundles/pipelines/_models/rabbitmq_options.py @@ -0,0 +1,45 @@ +# Code generated by pydabs-codegen. DO NOT EDIT. + +from dataclasses import dataclass +from typing import TYPE_CHECKING, TypedDict + +from databricks.bundles.core._transform import _transform +from databricks.bundles.core._transform_to_json import _transform_to_json_value +from databricks.bundles.core._variable import VariableOr + +if TYPE_CHECKING: + from typing_extensions import Self + + +@dataclass(kw_only=True) +class RabbitmqOptions: + """ + RabbitMQ specific options for ingestion. + Performance tuning options (consumers_per_task, max_messages_per_fetch, etc.) + are intentionally not exposed in the public API. The managed connector uses + sensible defaults internally. These can be added later if user demand arises. + """ + + queue: VariableOr[str] + """ + [Beta] (Required) RabbitMQ queue name to consume from. + """ + + @classmethod + def from_dict(cls, value: "RabbitmqOptionsDict") -> "Self": + return _transform(cls, value) + + def as_dict(self) -> "RabbitmqOptionsDict": + return _transform_to_json_value(self) # type:ignore + + +class RabbitmqOptionsDict(TypedDict, total=False): + """""" + + queue: VariableOr[str] + """ + [Beta] (Required) RabbitMQ queue name to consume from. + """ + + +RabbitmqOptionsParam = RabbitmqOptionsDict | RabbitmqOptions diff --git a/python/databricks/bundles/pipelines/_models/schema_spec.py b/python/databricks/bundles/pipelines/_models/schema_spec.py index b3dd638c455..bfd9acef17d 100644 --- a/python/databricks/bundles/pipelines/_models/schema_spec.py +++ b/python/databricks/bundles/pipelines/_models/schema_spec.py @@ -37,15 +37,6 @@ class SchemaSpec: [Public Preview] Required. Destination schema to store tables in. Tables with the same name as the source tables are created in this destination schema. The pipeline fails If a table with the same name already exists. """ - source_schema: VariableOr[str] - """ - [Public Preview] Schema name in the source database. Currently required; this field will become optional in - an upcoming release, since some source types (for example streaming / message-bus connectors) - do not use it. When that change ships, this field's type in the generated SDKs and CLI will - change from required to optional (nullable); clients that assume it is always present should - handle its absence. - """ - connector_options: VariableOrOptional[ConnectorOptions] = None """ [Public Preview] (Optional) Source Specific Connector Options @@ -64,6 +55,13 @@ class SchemaSpec: [Public Preview] The source catalog name. Might be optional depending on the type of source. """ + source_schema: VariableOrOptional[str] = None + """ + [Public Preview] Schema name in the source database. Optional: some source types (for example streaming or + message-bus connectors) do not use it, so it may be absent from a pipeline's definition. + Clients that assume it is always present should handle its absence. + """ + table_configuration: VariableOrOptional[TableSpecificConfig] = None """ [Public Preview] Configuration settings to control the ingestion of tables. These settings are applied to all tables in this schema and override the table_configuration defined in the IngestionPipelineDefinition object. @@ -90,15 +88,6 @@ class SchemaSpecDict(TypedDict, total=False): [Public Preview] Required. Destination schema to store tables in. Tables with the same name as the source tables are created in this destination schema. The pipeline fails If a table with the same name already exists. """ - source_schema: VariableOr[str] - """ - [Public Preview] Schema name in the source database. Currently required; this field will become optional in - an upcoming release, since some source types (for example streaming / message-bus connectors) - do not use it. When that change ships, this field's type in the generated SDKs and CLI will - change from required to optional (nullable); clients that assume it is always present should - handle its absence. - """ - connector_options: VariableOrOptional[ConnectorOptionsParam] """ [Public Preview] (Optional) Source Specific Connector Options @@ -117,6 +106,13 @@ class SchemaSpecDict(TypedDict, total=False): [Public Preview] The source catalog name. Might be optional depending on the type of source. """ + source_schema: VariableOrOptional[str] + """ + [Public Preview] Schema name in the source database. Optional: some source types (for example streaming or + message-bus connectors) do not use it, so it may be absent from a pipeline's definition. + Clients that assume it is always present should handle its absence. + """ + table_configuration: VariableOrOptional[TableSpecificConfigParam] """ [Public Preview] Configuration settings to control the ingestion of tables. These settings are applied to all tables in this schema and override the table_configuration defined in the IngestionPipelineDefinition object. diff --git a/python/databricks/bundles/pipelines/_models/table_spec.py b/python/databricks/bundles/pipelines/_models/table_spec.py index 508a4acb7e6..dc75d872c71 100644 --- a/python/databricks/bundles/pipelines/_models/table_spec.py +++ b/python/databricks/bundles/pipelines/_models/table_spec.py @@ -33,15 +33,6 @@ class TableSpec: [Public Preview] Required. Destination schema to store table. """ - source_table: VariableOr[str] - """ - [Public Preview] Table name in the source database. Currently required; this field will become optional in - an upcoming release, since some source types (for example streaming / message-bus connectors) - do not use it. When that change ships, this field's type in the generated SDKs and CLI will - change from required to optional (nullable); clients that assume it is always present should - handle its absence. - """ - connector_options: VariableOrOptional[ConnectorOptions] = None """ [Public Preview] (Optional) Source Specific Connector Options @@ -62,6 +53,13 @@ class TableSpec: [Public Preview] Schema name in the source database. Might be optional depending on the type of source. """ + source_table: VariableOrOptional[str] = None + """ + [Public Preview] Table name in the source database. Optional: some source types (for example streaming or + message-bus connectors) do not use it, so it may be absent from a pipeline's definition. + Clients that assume it is always present should handle its absence. + """ + table_configuration: VariableOrOptional[TableSpecificConfig] = None """ [Public Preview] Configuration settings to control the ingestion of tables. These settings override the table_configuration defined in the IngestionPipelineDefinition object and the SchemaSpec. @@ -88,15 +86,6 @@ class TableSpecDict(TypedDict, total=False): [Public Preview] Required. Destination schema to store table. """ - source_table: VariableOr[str] - """ - [Public Preview] Table name in the source database. Currently required; this field will become optional in - an upcoming release, since some source types (for example streaming / message-bus connectors) - do not use it. When that change ships, this field's type in the generated SDKs and CLI will - change from required to optional (nullable); clients that assume it is always present should - handle its absence. - """ - connector_options: VariableOrOptional[ConnectorOptionsParam] """ [Public Preview] (Optional) Source Specific Connector Options @@ -117,6 +106,13 @@ class TableSpecDict(TypedDict, total=False): [Public Preview] Schema name in the source database. Might be optional depending on the type of source. """ + source_table: VariableOrOptional[str] + """ + [Public Preview] Table name in the source database. Optional: some source types (for example streaming or + message-bus connectors) do not use it, so it may be absent from a pipeline's definition. + Clients that assume it is always present should handle its absence. + """ + table_configuration: VariableOrOptional[TableSpecificConfigParam] """ [Public Preview] Configuration settings to control the ingestion of tables. These settings override the table_configuration defined in the IngestionPipelineDefinition object and the SchemaSpec. From 686d31b7d68f6b1f60d79fc570d548c3ee6af70a Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Mon, 31 Aug 2026 12:56:46 +0000 Subject: [PATCH 02/22] Add postgres_snapshot_schedules bundle resource MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Changes Add the `postgres_snapshot_schedules` bundle resource, which manages the automatic-snapshot schedule of a Lakebase Postgres branch. The snapshot schedule is a per-branch singleton with no create or delete API — only `GetSnapshotSchedule` and `UpdateSnapshotSchedule`. The resource maps the lifecycle onto that single write call: - create/update set the branch's schedule via `UpdateSnapshotSchedule` (update_mask `schedule`, awaiting the long-running operation); - delete disables automatic snapshots by setting an empty cadence set, since DoDelete also fires when the resource is removed from config, not only on `bundle destroy`; - `branch` composes the schedule's hierarchical name and is a provided id field (a change recreates). Modeled on the existing `postgres_*` resources. Direct engine only: the schedule was added in databricks-sdk-go v0.177.0 and the pinned Terraform provider has no equivalent resource yet, so the acceptance and bind tests are pinned to the direct engine. ## Tests - direct-engine unit CRUD (`bundle/direct/dresources`); - acceptance (direct engine), four end-to-end scenarios, each reading the schedule back with `postgres get-snapshot-schedule`: - `basic`: create with a cadence, in-place cadence update, then remove the resource from config, which disables the schedule (reads back `schedule: null`); - `update`: add the schedule to an already-deployed branch, then remove it; - `out-of-band`: an out-of-band `update-snapshot-schedule` is detected as drift by `bundle plan` (`update postgres_snapshot_schedules.main_schedule`) and reconciled back by deploy; - `orphaned`: removing the branch from config while keeping the schedule that references it — the reference still resolves from the deployed state, so validate passes and plan sequences a branch delete alongside a schedule recreate (documented, not a validation error); - the invariant and bind/unbind suites; - resource-enumeration unit tests (bind support, run_as, permissions, target-mode) extended for the new type. Acceptance goldens regenerated via `-update`; the verify pass is green apart from pre-existing load-induced terraform-engine timeout flakes, each confirmed passing in isolation. Co-authored-by: Isaac --- .../bundles/postgres-snapshot-schedules.md | 1 + .../postgres_snapshot_schedule/databricks.yml | 11 + .../postgres_snapshot_schedule/out.test.toml | 2 + .../postgres_snapshot_schedule/output.txt | 30 +++ .../bind/postgres_snapshot_schedule/script | 6 + .../bind/postgres_snapshot_schedule/test.toml | 26 +++ .../postgres_snapshot_schedule.yml.tmpl | 22 ++ acceptance/bundle/refschema/out.fields.txt | 18 ++ .../basic/databricks.yml.tmpl | 26 +++ .../basic/out.requests.create.txt | 46 ++++ .../basic/out.requests.remove.txt | 28 +++ .../basic/out.requests.update.txt | 41 ++++ .../basic/out.test.toml | 4 + .../basic/output.txt | 93 ++++++++ .../postgres_snapshot_schedules/basic/script | 27 +++ .../orphaned/databricks.yml.tmpl | 26 +++ .../orphaned/out.test.toml | 4 + .../orphaned/output.txt | 61 +++++ .../orphaned/script | 27 +++ .../out-of-band/databricks.yml.tmpl | 26 +++ .../out-of-band/out.test.toml | 4 + .../out-of-band/output.txt | 80 +++++++ .../out-of-band/script | 22 ++ .../script.prepare | 6 + .../postgres_snapshot_schedules/test.toml | 16 ++ .../update/databricks.yml.tmpl | 26 +++ .../update/out.requests.add.txt | 74 ++++++ .../update/out.requests.remove.txt | 40 ++++ .../update/out.test.toml | 4 + .../update/output.txt | 95 ++++++++ .../postgres_snapshot_schedules/update/script | 28 +++ .../apply_bundle_permissions_test.go | 1 + .../resourcemutator/apply_target_mode_test.go | 7 + .../mutator/resourcemutator/run_as_test.go | 2 + bundle/config/resources.go | 133 +++++------ .../resources/postgres_snapshot_schedule.go | 73 ++++++ bundle/config/resources_test.go | 23 +- bundle/direct/dresources/all.go | 69 +++--- bundle/direct/dresources/all_test.go | 37 ++- .../dresources/postgres_snapshot_schedule.go | 131 +++++++++++ bundle/direct/dresources/resources.yml | 8 + bundle/internal/schema/annotations.yml | 13 ++ bundle/schema/jsonschema.json | 214 ++++++++++++++++++ libs/testserver/fake_workspace.go | 18 +- libs/testserver/handlers.go | 16 ++ libs/testserver/postgres.go | 61 +++++ 46 files changed, 1611 insertions(+), 115 deletions(-) create mode 100644 .nextchanges/bundles/postgres-snapshot-schedules.md create mode 100644 acceptance/bundle/deployment/bind/postgres_snapshot_schedule/databricks.yml create mode 100644 acceptance/bundle/deployment/bind/postgres_snapshot_schedule/out.test.toml create mode 100644 acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt create mode 100644 acceptance/bundle/deployment/bind/postgres_snapshot_schedule/script create mode 100644 acceptance/bundle/deployment/bind/postgres_snapshot_schedule/test.toml create mode 100644 acceptance/bundle/invariant/configs/postgres_snapshot_schedule.yml.tmpl create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/basic/databricks.yml.tmpl create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.create.txt create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.remove.txt create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.update.txt create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.test.toml create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/basic/output.txt create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/basic/script create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/databricks.yml.tmpl create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/out.test.toml create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/output.txt create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/script create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/databricks.yml.tmpl create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/out.test.toml create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/output.txt create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/script create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/script.prepare create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/test.toml create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/update/databricks.yml.tmpl create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/update/out.requests.add.txt create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/update/out.requests.remove.txt create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/update/out.test.toml create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/update/output.txt create mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/update/script create mode 100644 bundle/config/resources/postgres_snapshot_schedule.go create mode 100644 bundle/direct/dresources/postgres_snapshot_schedule.go diff --git a/.nextchanges/bundles/postgres-snapshot-schedules.md b/.nextchanges/bundles/postgres-snapshot-schedules.md new file mode 100644 index 00000000000..b54efd7611f --- /dev/null +++ b/.nextchanges/bundles/postgres-snapshot-schedules.md @@ -0,0 +1 @@ +Add the `postgres_snapshot_schedules` bundle resource for managing a Lakebase Postgres branch's automatic-snapshot schedule (direct deployment engine only). diff --git a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/databricks.yml b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/databricks.yml new file mode 100644 index 00000000000..d680805158d --- /dev/null +++ b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/databricks.yml @@ -0,0 +1,11 @@ +bundle: + name: test-bundle + +resources: + postgres_snapshot_schedules: + schedule1: + branch: projects/test-project/branches/main + schedule: + - daily_schedule: + hour: 3 + retention: "604800s" diff --git a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/out.test.toml b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/out.test.toml new file mode 100644 index 00000000000..0938e678987 --- /dev/null +++ b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/out.test.toml @@ -0,0 +1,2 @@ +Cloud = false +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt new file mode 100644 index 00000000000..71102ecfd2c --- /dev/null +++ b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt @@ -0,0 +1,30 @@ + +>>> [CLI] bundle deployment bind schedule1 projects/test-project/branches/main/snapshot-schedule --auto-approve +Successfully bound postgres_snapshot_schedule with an id 'projects/test-project/branches/main/snapshot-schedule' +Run 'bundle deploy' to deploy changes to your workspace + +>>> [CLI] bundle summary +Name: test-bundle +Target: default +Workspace: + User: [USERNAME] + Path: /Workspace/Users/[USERNAME]/.bundle/test-bundle/default +Resources: + Postgres snapshot schedules: + schedule1: + Name: + URL: (not deployed) + +>>> [CLI] bundle deployment unbind schedule1 + +>>> [CLI] bundle summary +Name: test-bundle +Target: default +Workspace: + User: [USERNAME] + Path: /Workspace/Users/[USERNAME]/.bundle/test-bundle/default +Resources: + Postgres snapshot schedules: + schedule1: + Name: + URL: (not deployed) diff --git a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/script b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/script new file mode 100644 index 00000000000..ee70c6a35bd --- /dev/null +++ b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/script @@ -0,0 +1,6 @@ +SCHEDULE_NAME="projects/test-project/branches/main/snapshot-schedule" +trace $CLI bundle deployment bind schedule1 "${SCHEDULE_NAME}" --auto-approve +trace $CLI bundle summary + +trace $CLI bundle deployment unbind schedule1 +trace $CLI bundle summary diff --git a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/test.toml b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/test.toml new file mode 100644 index 00000000000..dc7816a8cd1 --- /dev/null +++ b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/test.toml @@ -0,0 +1,26 @@ +Cloud = false + +# The snapshot schedule was added to the Postgres API in databricks-sdk-go +# v0.177.0, which the pinned Terraform provider does not yet include, so there is +# no databricks_..._snapshot_schedule resource. Run the direct engine only. +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] + +Ignore = [ + ".databricks" +] + +[[Server]] +Pattern = "GET /api/2.0/postgres/projects/test-project/branches/main/snapshot-schedule" +Response.Body = ''' +{ + "name": "projects/test-project/branches/main/snapshot-schedule", + "schedule": [ + { + "daily_schedule": { + "hour": 3 + }, + "retention": "604800s" + } + ] +} +''' diff --git a/acceptance/bundle/invariant/configs/postgres_snapshot_schedule.yml.tmpl b/acceptance/bundle/invariant/configs/postgres_snapshot_schedule.yml.tmpl new file mode 100644 index 00000000000..5e36e89886c --- /dev/null +++ b/acceptance/bundle/invariant/configs/postgres_snapshot_schedule.yml.tmpl @@ -0,0 +1,22 @@ +bundle: + name: test-bundle-$UNIQUE_NAME + +resources: + postgres_projects: + project: + project_id: test-pg-project-$UNIQUE_NAME + display_name: Test Postgres Project + + postgres_branches: + foo: + parent: ${resources.postgres_projects.project.name} + branch_id: test-branch-$UNIQUE_NAME + no_expiry: true + + postgres_snapshot_schedules: + foo: + branch: ${resources.postgres_branches.foo.name} + schedule: + - daily_schedule: + hour: 3 + retention: "604800s" diff --git a/acceptance/bundle/refschema/out.fields.txt b/acceptance/bundle/refschema/out.fields.txt index 748939d3c56..b231604a2ba 100644 --- a/acceptance/bundle/refschema/out.fields.txt +++ b/acceptance/bundle/refschema/out.fields.txt @@ -3556,6 +3556,24 @@ resources.postgres_roles.*.status.postgres_role string REMOTE resources.postgres_roles.*.status.role_id string REMOTE resources.postgres_roles.*.update_time *time.Time REMOTE resources.postgres_roles.*.url string INPUT +resources.postgres_snapshot_schedules.*.branch string ALL +resources.postgres_snapshot_schedules.*.id string INPUT +resources.postgres_snapshot_schedules.*.lifecycle resources.Lifecycle INPUT +resources.postgres_snapshot_schedules.*.lifecycle.prevent_destroy bool INPUT +resources.postgres_snapshot_schedules.*.modified_status string INPUT +resources.postgres_snapshot_schedules.*.name string REMOTE +resources.postgres_snapshot_schedules.*.schedule []postgres.ScheduleCadence ALL +resources.postgres_snapshot_schedules.*.schedule[*] postgres.ScheduleCadence ALL +resources.postgres_snapshot_schedules.*.schedule[*].daily_schedule *postgres.DailySchedule ALL +resources.postgres_snapshot_schedules.*.schedule[*].daily_schedule.hour int ALL +resources.postgres_snapshot_schedules.*.schedule[*].monthly_schedule *postgres.MonthlySchedule ALL +resources.postgres_snapshot_schedules.*.schedule[*].monthly_schedule.day int ALL +resources.postgres_snapshot_schedules.*.schedule[*].monthly_schedule.hour int ALL +resources.postgres_snapshot_schedules.*.schedule[*].retention duration.Duration ALL +resources.postgres_snapshot_schedules.*.schedule[*].weekly_schedule *postgres.WeeklySchedule ALL +resources.postgres_snapshot_schedules.*.schedule[*].weekly_schedule.day_of_week postgres.DayOfWeek ALL +resources.postgres_snapshot_schedules.*.schedule[*].weekly_schedule.hour int ALL +resources.postgres_snapshot_schedules.*.url string INPUT resources.postgres_synced_tables.*.accelerated_sync bool ALL resources.postgres_synced_tables.*.branch string ALL resources.postgres_synced_tables.*.create_database_objects_if_missing bool ALL diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/databricks.yml.tmpl b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/databricks.yml.tmpl new file mode 100644 index 00000000000..a951ec2a7cd --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/databricks.yml.tmpl @@ -0,0 +1,26 @@ +bundle: + name: deploy-pg-ss-basic-$UNIQUE_NAME + +sync: + paths: [] + +resources: + postgres_projects: + my_project: + project_id: test-pg-proj-$UNIQUE_NAME + display_name: "Test Project for Snapshot Schedules" + pg_version: 16 + + postgres_branches: + main: + parent: ${resources.postgres_projects.my_project.id} + branch_id: main + no_expiry: true + + postgres_snapshot_schedules: + main_schedule: + branch: ${resources.postgres_branches.main.id} + schedule: + - daily_schedule: + hour: 3 + retention: "604800s" diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.create.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.create.txt new file mode 100644 index 00000000000..28332f384de --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.create.txt @@ -0,0 +1,46 @@ +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" +} +{ + "method": "PATCH", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "q": { + "update_mask": "schedule" + }, + "body": { + "schedule": [ + { + "daily_schedule": { + "hour": 3 + }, + "retention": "604800s" + } + ] + } +} +{ + "method": "POST", + "path": "/api/2.0/postgres/projects", + "q": { + "project_id": "test-pg-proj-[UNIQUE_NAME]" + }, + "body": { + "spec": { + "display_name": "Test Project for Snapshot Schedules", + "pg_version": 16 + } + } +} +{ + "method": "POST", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches", + "q": { + "branch_id": "main" + }, + "body": { + "spec": { + "no_expiry": true + } + } +} diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.remove.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.remove.txt new file mode 100644 index 00000000000..9b0ebd46820 --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.remove.txt @@ -0,0 +1,28 @@ +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" +} +{ + "method": "PATCH", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "q": { + "update_mask": "schedule" + }, + "body": {} +} diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.update.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.update.txt new file mode 100644 index 00000000000..dcaaf4977e1 --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.update.txt @@ -0,0 +1,41 @@ +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" +} +{ + "method": "PATCH", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "q": { + "update_mask": "schedule" + }, + "body": { + "schedule": [ + { + "daily_schedule": { + "hour": 5 + }, + "retention": "604800s" + } + ] + } +} diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.test.toml b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.test.toml new file mode 100644 index 00000000000..1314e661c24 --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.test.toml @@ -0,0 +1,4 @@ +Cloud = true +CloudEnvs.azure = false +CloudEnvs.gcp = false +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/output.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/output.txt new file mode 100644 index 00000000000..1d39ab41bca --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/output.txt @@ -0,0 +1,93 @@ + +=== Create with a snapshot schedule +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-basic-[UNIQUE_NAME]/default/files... +Created postgres_branches.main +Created postgres_projects.my_project +Created postgres_snapshot_schedules.main_schedule +Files: 0 uploaded, 0 deleted +Resources: 3 created, 0 changed, 0 deleted, 0 unchanged + +>>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule +{ + "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "schedule": [ + { + "daily_schedule": { + "hour": 3 + }, + "retention": "604800s" + } + ] +} + +=== Update the schedule cadence +>>> [CLI] bundle deploy --auto-approve +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-basic-[UNIQUE_NAME]/default/files... +Updated postgres_snapshot_schedules.main_schedule +Files: 0 uploaded, 0 deleted +Resources: 0 created, 1 changed, 0 deleted, 2 unchanged + +>>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule +{ + "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "schedule": [ + { + "daily_schedule": { + "hour": 5 + }, + "retention": "604800s" + } + ] +} + +=== Remove the snapshot schedule resource (disables automatic snapshots) +>>> cat databricks.yml +bundle: + name: deploy-pg-ss-basic-[UNIQUE_NAME] + +sync: + paths: [] + +resources: + postgres_projects: + my_project: + project_id: test-pg-proj-[UNIQUE_NAME] + display_name: "Test Project for Snapshot Schedules" + pg_version: 16 + + postgres_branches: + main: + parent: ${resources.postgres_projects.my_project.id} + branch_id: main + no_expiry: true + + +>>> [CLI] bundle deploy --auto-approve +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-basic-[UNIQUE_NAME]/default/files... +Deleted postgres_snapshot_schedules.main_schedule +Files: 0 uploaded, 0 deleted +Resources: 0 created, 0 changed, 1 deleted, 2 unchanged + +>>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule +{ + "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "schedule": null +} + +>>> [CLI] bundle destroy --auto-approve +The following resources will be deleted: + delete resources.postgres_branches.main + delete resources.postgres_projects.my_project + +This action will result in the deletion of the following Lakebase projects along with +all their branches, databases, and endpoints. All data stored in them will be permanently lost: + delete resources.postgres_projects.my_project + +This action will result in the deletion of the following Lakebase branches. +All data stored in them will be permanently lost: + delete resources.postgres_branches.main + +All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-basic-[UNIQUE_NAME]/default + +Destroy: 2 deleted diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/script b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/script new file mode 100644 index 00000000000..0e7cbe6b7cb --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/script @@ -0,0 +1,27 @@ +cleanup() { + trace $CLI bundle destroy --auto-approve + rm -f out.requests.txt +} +trap cleanup EXIT + +schedule_name="projects/test-pg-proj-${UNIQUE_NAME}/branches/main/snapshot-schedule" + +title "Create with a snapshot schedule" +envsubst < databricks.yml.tmpl > databricks.yml +rm -f out.requests.txt +trace $CLI bundle deploy +trace $CLI postgres get-snapshot-schedule "${schedule_name}" | snapshot_schedule_fields +print_requests.py --del-body parent,project_id,branch_id --sort --get '//postgres' '^//workspace-files/' '^//workspace/' '^//telemetry-ext' '^//operations/' > out.requests.create.txt + +title "Update the schedule cadence" +sed "s/hour: 3/hour: 5/" databricks.yml > databricks.yml.new && mv databricks.yml.new databricks.yml +trace $CLI bundle deploy --auto-approve +trace $CLI postgres get-snapshot-schedule "${schedule_name}" | snapshot_schedule_fields +print_requests.py --del-body parent,project_id,branch_id --sort --get '//postgres' '^//workspace-files/' '^//workspace/' '^//telemetry-ext' '^//operations/' > out.requests.update.txt + +title "Remove the snapshot schedule resource (disables automatic snapshots)" +sed '/postgres_snapshot_schedules:/,$d' databricks.yml > databricks.yml.new && mv databricks.yml.new databricks.yml +trace cat databricks.yml +trace $CLI bundle deploy --auto-approve +trace $CLI postgres get-snapshot-schedule "${schedule_name}" | snapshot_schedule_fields +print_requests.py --del-body parent,project_id,branch_id --sort --get '//postgres' '^//workspace-files/' '^//workspace/' '^//telemetry-ext' '^//operations/' > out.requests.remove.txt diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/databricks.yml.tmpl b/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/databricks.yml.tmpl new file mode 100644 index 00000000000..f2ad5af11a6 --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/databricks.yml.tmpl @@ -0,0 +1,26 @@ +bundle: + name: deploy-pg-ss-orphaned-$UNIQUE_NAME + +sync: + paths: [] + +resources: + postgres_projects: + my_project: + project_id: test-pg-proj-$UNIQUE_NAME + display_name: "Test Project for Snapshot Schedules" + pg_version: 16 + + postgres_branches: + main: + parent: ${resources.postgres_projects.my_project.id} + branch_id: main + no_expiry: true + + postgres_snapshot_schedules: + main_schedule: + branch: ${resources.postgres_branches.main.id} + schedule: + - daily_schedule: + hour: 3 + retention: "604800s" diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/out.test.toml b/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/out.test.toml new file mode 100644 index 00000000000..1314e661c24 --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/out.test.toml @@ -0,0 +1,4 @@ +Cloud = true +CloudEnvs.azure = false +CloudEnvs.gcp = false +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/output.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/output.txt new file mode 100644 index 00000000000..5cc6d36335e --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/output.txt @@ -0,0 +1,61 @@ + +=== Deploy project + branch + snapshot schedule +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-orphaned-[UNIQUE_NAME]/default/files... +Created postgres_branches.main +Created postgres_projects.my_project +Created postgres_snapshot_schedules.main_schedule +Files: 0 uploaded, 0 deleted +Resources: 3 created, 0 changed, 0 deleted, 0 unchanged + +=== Remove the branch but keep the schedule that references it +>>> cat databricks.yml +bundle: + name: deploy-pg-ss-orphaned-[UNIQUE_NAME] + +sync: + paths: [] + +resources: + postgres_projects: + my_project: + project_id: test-pg-proj-[UNIQUE_NAME] + display_name: "Test Project for Snapshot Schedules" + pg_version: 16 + + postgres_snapshot_schedules: + main_schedule: + branch: ${resources.postgres_branches.main.id} + schedule: + - daily_schedule: + hour: 3 + retention: "604800s" +Name: deploy-pg-ss-orphaned-[UNIQUE_NAME] +Target: default +Workspace: + User: [USERNAME] + Path: /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-orphaned-[UNIQUE_NAME]/default + +Validation OK! +delete postgres_branches.main +recreate postgres_snapshot_schedules.main_schedule + +Plan: 1 to add, 0 to change, 2 to delete, 1 unchanged + +>>> [CLI] bundle destroy --auto-approve +The following resources will be deleted: + delete resources.postgres_branches.main + delete resources.postgres_projects.my_project + delete resources.postgres_snapshot_schedules.main_schedule + +This action will result in the deletion of the following Lakebase projects along with +all their branches, databases, and endpoints. All data stored in them will be permanently lost: + delete resources.postgres_projects.my_project + +This action will result in the deletion of the following Lakebase branches. +All data stored in them will be permanently lost: + delete resources.postgres_branches.main + +All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-orphaned-[UNIQUE_NAME]/default + +Destroy: 3 deleted diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/script b/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/script new file mode 100644 index 00000000000..f89a3ad4a87 --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/script @@ -0,0 +1,27 @@ +cleanup() { + trace $CLI bundle destroy --auto-approve + rm -f out.requests.txt +} +trap cleanup EXIT + +title "Deploy project + branch + snapshot schedule" +envsubst < databricks.yml.tmpl > databricks.yml +trace $CLI bundle deploy + +# Remove ONLY the branch from config while keeping the snapshot schedule, which +# still references ${resources.postgres_branches.main.id}. The reference still +# resolves from the deployed state (the branch is present in state during the +# transition), so this does NOT fail as a dangling reference: validate passes and +# plan sequences a delete of the branch alongside a recreate of the schedule. +# Deploying that plan would fail at apply (the schedule cannot be created on a +# deleted branch); this test documents the plan-time behavior. Acceptable user +# error -- removing a parent while keeping a child that references it. +# errcode records the exit code so the outcome is captured deterministically. +title "Remove the branch but keep the schedule that references it" +sed '/^ postgres_branches:/,/^ postgres_snapshot_schedules:/{/^ postgres_snapshot_schedules:/!d}' databricks.yml > databricks.yml.new && mv databricks.yml.new databricks.yml +trace cat databricks.yml +errcode $CLI bundle validate +errcode $CLI bundle plan + +# Restore the full config so the destroy in cleanup can resolve references. +envsubst < databricks.yml.tmpl > databricks.yml diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/databricks.yml.tmpl b/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/databricks.yml.tmpl new file mode 100644 index 00000000000..e24897277b9 --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/databricks.yml.tmpl @@ -0,0 +1,26 @@ +bundle: + name: deploy-pg-ss-oob-$UNIQUE_NAME + +sync: + paths: [] + +resources: + postgres_projects: + my_project: + project_id: test-pg-proj-$UNIQUE_NAME + display_name: "Test Project for Snapshot Schedules" + pg_version: 16 + + postgres_branches: + main: + parent: ${resources.postgres_projects.my_project.id} + branch_id: main + no_expiry: true + + postgres_snapshot_schedules: + main_schedule: + branch: ${resources.postgres_branches.main.id} + schedule: + - daily_schedule: + hour: 3 + retention: "604800s" diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/out.test.toml b/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/out.test.toml new file mode 100644 index 00000000000..1314e661c24 --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/out.test.toml @@ -0,0 +1,4 @@ +Cloud = true +CloudEnvs.azure = false +CloudEnvs.gcp = false +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/output.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/output.txt new file mode 100644 index 00000000000..41786d6076c --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/output.txt @@ -0,0 +1,80 @@ + +=== Deploy with a snapshot schedule +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-oob-[UNIQUE_NAME]/default/files... +Created postgres_branches.main +Created postgres_projects.my_project +Created postgres_snapshot_schedules.main_schedule +Files: 0 uploaded, 0 deleted +Resources: 3 created, 0 changed, 0 deleted, 0 unchanged + +>>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule +{ + "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "schedule": [ + { + "daily_schedule": { + "hour": 3 + }, + "retention": "604800s" + } + ] +} + +=== Change the schedule out of band via a direct API call +>>> [CLI] postgres update-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule schedule --json {"schedule":[{"daily_schedule":{"hour":9},"retention":"604800s"}]} +{ + "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "schedule": [ + { + "daily_schedule": { + "hour": 9 + }, + "retention": "604800s" + } + ] +} + +=== Plan detects the drift +>>> [CLI] bundle plan +update postgres_snapshot_schedules.main_schedule + +Plan: 0 to add, 1 to change, 0 to delete, 2 unchanged + +=== Deploy reconciles the schedule back to the configured cadence +>>> [CLI] bundle deploy --auto-approve +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-oob-[UNIQUE_NAME]/default/files... +Updated postgres_snapshot_schedules.main_schedule +Files: 0 uploaded, 0 deleted +Resources: 0 created, 1 changed, 0 deleted, 2 unchanged + +>>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule +{ + "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "schedule": [ + { + "daily_schedule": { + "hour": 3 + }, + "retention": "604800s" + } + ] +} + +>>> [CLI] bundle destroy --auto-approve +The following resources will be deleted: + delete resources.postgres_branches.main + delete resources.postgres_projects.my_project + delete resources.postgres_snapshot_schedules.main_schedule + +This action will result in the deletion of the following Lakebase projects along with +all their branches, databases, and endpoints. All data stored in them will be permanently lost: + delete resources.postgres_projects.my_project + +This action will result in the deletion of the following Lakebase branches. +All data stored in them will be permanently lost: + delete resources.postgres_branches.main + +All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-oob-[UNIQUE_NAME]/default + +Destroy: 3 deleted diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/script b/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/script new file mode 100644 index 00000000000..59d2cf6254e --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/script @@ -0,0 +1,22 @@ +cleanup() { + trace $CLI bundle destroy --auto-approve + rm -f out.requests.txt +} +trap cleanup EXIT + +schedule_name="projects/test-pg-proj-${UNIQUE_NAME}/branches/main/snapshot-schedule" + +title "Deploy with a snapshot schedule" +envsubst < databricks.yml.tmpl > databricks.yml +trace $CLI bundle deploy +trace $CLI postgres get-snapshot-schedule "${schedule_name}" | snapshot_schedule_fields + +title "Change the schedule out of band via a direct API call" +trace $CLI postgres update-snapshot-schedule "${schedule_name}" schedule --json '{"schedule":[{"daily_schedule":{"hour":9},"retention":"604800s"}]}' | snapshot_schedule_fields + +title "Plan detects the drift" +trace $CLI bundle plan + +title "Deploy reconciles the schedule back to the configured cadence" +trace $CLI bundle deploy --auto-approve +trace $CLI postgres get-snapshot-schedule "${schedule_name}" | snapshot_schedule_fields diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/script.prepare b/acceptance/bundle/resources/postgres_snapshot_schedules/script.prepare new file mode 100644 index 00000000000..ce34a2474d5 --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/script.prepare @@ -0,0 +1,6 @@ +# snapshot_schedule_fields is the allow-list of snapshot-schedule fields the +# acceptance tests assert on. Anything the backend returns outside this list is +# dropped, so a new field in the API response does not break the golden. +snapshot_schedule_fields() { + jq '{name, schedule}' +} diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/test.toml b/acceptance/bundle/resources/postgres_snapshot_schedules/test.toml new file mode 100644 index 00000000000..888670d085c --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/test.toml @@ -0,0 +1,16 @@ +Cloud = true + +# Lakebase v2 (postgres) is only available in AWS as of January 2026 +CloudEnvs.gcp = false +CloudEnvs.azure = false + +# The snapshot schedule was added to the Postgres API in databricks-sdk-go +# v0.177.0, which the pinned Terraform provider does not yet include, so there is +# no databricks_..._snapshot_schedule resource to deploy through. Run the direct +# engine only until the provider catches up. +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] + +Ignore = [ + "databricks.yml", + ".databricks", +] diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/update/databricks.yml.tmpl b/acceptance/bundle/resources/postgres_snapshot_schedules/update/databricks.yml.tmpl new file mode 100644 index 00000000000..0ea6ec13414 --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/update/databricks.yml.tmpl @@ -0,0 +1,26 @@ +bundle: + name: deploy-pg-ss-update-$UNIQUE_NAME + +sync: + paths: [] + +resources: + postgres_projects: + my_project: + project_id: test-pg-proj-$UNIQUE_NAME + display_name: "Test Project for Snapshot Schedules" + pg_version: 16 + + postgres_branches: + main: + parent: ${resources.postgres_projects.my_project.id} + branch_id: main + no_expiry: true + + postgres_snapshot_schedules: + main_schedule: + branch: ${resources.postgres_branches.main.id} + schedule: + - daily_schedule: + hour: 3 + retention: "604800s" diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.requests.add.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.requests.add.txt new file mode 100644 index 00000000000..9c5f1edf5c9 --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.requests.add.txt @@ -0,0 +1,74 @@ +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" +} +{ + "method": "PATCH", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "q": { + "update_mask": "schedule" + }, + "body": { + "schedule": [ + { + "daily_schedule": { + "hour": 3 + }, + "retention": "604800s" + } + ] + } +} +{ + "method": "POST", + "path": "/api/2.0/postgres/projects", + "q": { + "project_id": "test-pg-proj-[UNIQUE_NAME]" + }, + "body": { + "spec": { + "display_name": "Test Project for Snapshot Schedules", + "pg_version": 16 + } + } +} +{ + "method": "POST", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches", + "q": { + "branch_id": "main" + }, + "body": { + "spec": { + "no_expiry": true + } + } +} diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.requests.remove.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.requests.remove.txt new file mode 100644 index 00000000000..bea13bc3b2a --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.requests.remove.txt @@ -0,0 +1,40 @@ +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" +} +{ + "method": "GET", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" +} +{ + "method": "PATCH", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "q": { + "update_mask": "schedule" + }, + "body": {} +} diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.test.toml b/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.test.toml new file mode 100644 index 00000000000..1314e661c24 --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.test.toml @@ -0,0 +1,4 @@ +Cloud = true +CloudEnvs.azure = false +CloudEnvs.gcp = false +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/update/output.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/update/output.txt new file mode 100644 index 00000000000..1672fc03e07 --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/update/output.txt @@ -0,0 +1,95 @@ + +=== Deploy project + branch without a snapshot schedule +>>> cat databricks.yml +bundle: + name: deploy-pg-ss-update-[UNIQUE_NAME] + +sync: + paths: [] + +resources: + postgres_projects: + my_project: + project_id: test-pg-proj-[UNIQUE_NAME] + display_name: "Test Project for Snapshot Schedules" + pg_version: 16 + + postgres_branches: + main: + parent: ${resources.postgres_projects.my_project.id} + branch_id: main + no_expiry: true + + +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-update-[UNIQUE_NAME]/default/files... +Created postgres_branches.main +Created postgres_projects.my_project +Files: 0 uploaded, 0 deleted +Resources: 2 created, 0 changed, 0 deleted, 0 unchanged + +>>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule +{ + "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "schedule": null +} + +=== Add the snapshot schedule resource to the existing branch +>>> [CLI] bundle plan +create postgres_snapshot_schedules.main_schedule + +Plan: 1 to add, 0 to change, 0 to delete, 2 unchanged + +>>> [CLI] bundle deploy --auto-approve +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-update-[UNIQUE_NAME]/default/files... +Created postgres_snapshot_schedules.main_schedule +Files: 0 uploaded, 0 deleted +Resources: 1 created, 0 changed, 0 deleted, 2 unchanged + +>>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule +{ + "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "schedule": [ + { + "daily_schedule": { + "hour": 3 + }, + "retention": "604800s" + } + ] +} + +=== Remove the snapshot schedule resource from the existing branch +>>> [CLI] bundle plan +delete postgres_snapshot_schedules.main_schedule + +Plan: 0 to add, 0 to change, 1 to delete, 2 unchanged + +>>> [CLI] bundle deploy --auto-approve +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-update-[UNIQUE_NAME]/default/files... +Deleted postgres_snapshot_schedules.main_schedule +Files: 0 uploaded, 0 deleted +Resources: 0 created, 0 changed, 1 deleted, 2 unchanged + +>>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule +{ + "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "schedule": null +} + +>>> [CLI] bundle destroy --auto-approve +The following resources will be deleted: + delete resources.postgres_branches.main + delete resources.postgres_projects.my_project + +This action will result in the deletion of the following Lakebase projects along with +all their branches, databases, and endpoints. All data stored in them will be permanently lost: + delete resources.postgres_projects.my_project + +This action will result in the deletion of the following Lakebase branches. +All data stored in them will be permanently lost: + delete resources.postgres_branches.main + +All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-update-[UNIQUE_NAME]/default + +Destroy: 2 deleted diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/update/script b/acceptance/bundle/resources/postgres_snapshot_schedules/update/script new file mode 100644 index 00000000000..6f69cc68102 --- /dev/null +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/update/script @@ -0,0 +1,28 @@ +cleanup() { + trace $CLI bundle destroy --auto-approve + rm -f out.requests.txt +} +trap cleanup EXIT + +schedule_name="projects/test-pg-proj-${UNIQUE_NAME}/branches/main/snapshot-schedule" + +title "Deploy project + branch without a snapshot schedule" +envsubst < databricks.yml.tmpl | sed '/postgres_snapshot_schedules:/,$d' > databricks.yml +trace cat databricks.yml +rm -f out.requests.txt +trace $CLI bundle deploy +trace $CLI postgres get-snapshot-schedule "${schedule_name}" | snapshot_schedule_fields + +title "Add the snapshot schedule resource to the existing branch" +envsubst < databricks.yml.tmpl > databricks.yml +trace $CLI bundle plan +trace $CLI bundle deploy --auto-approve +trace $CLI postgres get-snapshot-schedule "${schedule_name}" | snapshot_schedule_fields +print_requests.py --del-body parent,project_id,branch_id --sort --get '//postgres' '^//workspace-files/' '^//workspace/' '^//telemetry-ext' '^//operations/' > out.requests.add.txt + +title "Remove the snapshot schedule resource from the existing branch" +sed '/postgres_snapshot_schedules:/,$d' databricks.yml > databricks.yml.new && mv databricks.yml.new databricks.yml +trace $CLI bundle plan +trace $CLI bundle deploy --auto-approve +trace $CLI postgres get-snapshot-schedule "${schedule_name}" | snapshot_schedule_fields +print_requests.py --del-body parent,project_id,branch_id --sort --get '//postgres' '^//workspace-files/' '^//workspace/' '^//telemetry-ext' '^//operations/' > out.requests.remove.txt diff --git a/bundle/config/mutator/resourcemutator/apply_bundle_permissions_test.go b/bundle/config/mutator/resourcemutator/apply_bundle_permissions_test.go index 99ac6759ee8..27202a08dad 100644 --- a/bundle/config/mutator/resourcemutator/apply_bundle_permissions_test.go +++ b/bundle/config/mutator/resourcemutator/apply_bundle_permissions_test.go @@ -32,6 +32,7 @@ var unsupportedResources = []string{ "postgres_endpoints", "postgres_catalogs", "postgres_roles", + "postgres_snapshot_schedules", "postgres_synced_tables", "vector_search_indexes", "job_runs", diff --git a/bundle/config/mutator/resourcemutator/apply_target_mode_test.go b/bundle/config/mutator/resourcemutator/apply_target_mode_test.go index 08c76f8433d..eaf33516763 100644 --- a/bundle/config/mutator/resourcemutator/apply_target_mode_test.go +++ b/bundle/config/mutator/resourcemutator/apply_target_mode_test.go @@ -305,6 +305,13 @@ func mockBundle(mode config.Mode) *bundle.Bundle { }, }, }, + PostgresSnapshotSchedules: map[string]*resources.PostgresSnapshotSchedule{ + "postgres_snapshot_schedule1": { + PostgresSnapshotScheduleConfig: resources.PostgresSnapshotScheduleConfig{ + Branch: "projects/project1/branches/branch1", + }, + }, + }, VectorSearchEndpoints: map[string]*resources.VectorSearchEndpoint{ "vs_endpoint1": { CreateEndpoint: vectorsearch.CreateEndpoint{ diff --git a/bundle/config/mutator/resourcemutator/run_as_test.go b/bundle/config/mutator/resourcemutator/run_as_test.go index be9abfe6836..1df273c44b2 100644 --- a/bundle/config/mutator/resourcemutator/run_as_test.go +++ b/bundle/config/mutator/resourcemutator/run_as_test.go @@ -56,6 +56,7 @@ func allResourceTypes(t *testing.T) []string { "postgres_endpoints", "postgres_projects", "postgres_roles", + "postgres_snapshot_schedules", "postgres_synced_tables", "quality_monitors", "registered_models", @@ -191,6 +192,7 @@ var allowList = []string{ "postgres_endpoints", "postgres_projects", "postgres_roles", + "postgres_snapshot_schedules", "postgres_synced_tables", "registered_models", "experiments", diff --git a/bundle/config/resources.go b/bundle/config/resources.go index 633332a78c0..b5e68d992e8 100644 --- a/bundle/config/resources.go +++ b/bundle/config/resources.go @@ -15,37 +15,38 @@ type Resources struct { JobRuns map[string]*resources.JobRun `json:"job_runs,omitempty"` Pipelines map[string]*resources.Pipeline `json:"pipelines,omitempty"` - Models map[string]*resources.MlflowModel `json:"models,omitempty"` - Experiments map[string]*resources.MlflowExperiment `json:"experiments,omitempty"` - ModelServingEndpoints map[string]*resources.ModelServingEndpoint `json:"model_serving_endpoints,omitempty"` - RegisteredModels map[string]*resources.RegisteredModel `json:"registered_models,omitempty"` - QualityMonitors map[string]*resources.QualityMonitor `json:"quality_monitors,omitempty"` - Catalogs map[string]*resources.Catalog `json:"catalogs,omitempty"` - Schemas map[string]*resources.Schema `json:"schemas,omitempty"` - Volumes map[string]*resources.Volume `json:"volumes,omitempty"` - ExternalLocations map[string]*resources.ExternalLocation `json:"external_locations,omitempty"` - Clusters map[string]*resources.Cluster `json:"clusters,omitempty"` - Dashboards map[string]*resources.Dashboard `json:"dashboards,omitempty"` - GenieSpaces map[string]*resources.GenieSpace `json:"genie_spaces,omitempty"` - Apps map[string]*resources.App `json:"apps,omitempty"` - SecretScopes map[string]*resources.SecretScope `json:"secret_scopes,omitempty"` - Alerts map[string]*resources.Alert `json:"alerts,omitempty"` - SqlWarehouses map[string]*resources.SqlWarehouse `json:"sql_warehouses,omitempty"` - DatabaseInstances map[string]*resources.DatabaseInstance `json:"database_instances,omitempty"` - DatabaseCatalogs map[string]*resources.DatabaseCatalog `json:"database_catalogs,omitempty"` - SyncedDatabaseTables map[string]*resources.SyncedDatabaseTable `json:"synced_database_tables,omitempty"` - PostgresProjects map[string]*resources.PostgresProject `json:"postgres_projects,omitempty"` - PostgresBranches map[string]*resources.PostgresBranch `json:"postgres_branches,omitempty"` - PostgresEndpoints map[string]*resources.PostgresEndpoint `json:"postgres_endpoints,omitempty"` - PostgresCatalogs map[string]*resources.PostgresCatalog `json:"postgres_catalogs,omitempty"` - PostgresDatabases map[string]*resources.PostgresDatabase `json:"postgres_databases,omitempty"` - PostgresRoles map[string]*resources.PostgresRole `json:"postgres_roles,omitempty"` - PostgresSyncedTables map[string]*resources.PostgresSyncedTable `json:"postgres_synced_tables,omitempty"` - VectorSearchEndpoints map[string]*resources.VectorSearchEndpoint `json:"vector_search_endpoints,omitempty"` - VectorSearchIndexes map[string]*resources.VectorSearchIndex `json:"vector_search_indexes,omitempty"` - InstancePools map[string]*resources.InstancePool `json:"instance_pools,omitempty"` - Secrets map[string]*resources.Secret `json:"secrets,omitempty"` - ClusterPolicies map[string]*resources.ClusterPolicy `json:"cluster_policies,omitempty"` + Models map[string]*resources.MlflowModel `json:"models,omitempty"` + Experiments map[string]*resources.MlflowExperiment `json:"experiments,omitempty"` + ModelServingEndpoints map[string]*resources.ModelServingEndpoint `json:"model_serving_endpoints,omitempty"` + RegisteredModels map[string]*resources.RegisteredModel `json:"registered_models,omitempty"` + QualityMonitors map[string]*resources.QualityMonitor `json:"quality_monitors,omitempty"` + Catalogs map[string]*resources.Catalog `json:"catalogs,omitempty"` + Schemas map[string]*resources.Schema `json:"schemas,omitempty"` + Volumes map[string]*resources.Volume `json:"volumes,omitempty"` + ExternalLocations map[string]*resources.ExternalLocation `json:"external_locations,omitempty"` + Clusters map[string]*resources.Cluster `json:"clusters,omitempty"` + Dashboards map[string]*resources.Dashboard `json:"dashboards,omitempty"` + GenieSpaces map[string]*resources.GenieSpace `json:"genie_spaces,omitempty"` + Apps map[string]*resources.App `json:"apps,omitempty"` + SecretScopes map[string]*resources.SecretScope `json:"secret_scopes,omitempty"` + Alerts map[string]*resources.Alert `json:"alerts,omitempty"` + SqlWarehouses map[string]*resources.SqlWarehouse `json:"sql_warehouses,omitempty"` + DatabaseInstances map[string]*resources.DatabaseInstance `json:"database_instances,omitempty"` + DatabaseCatalogs map[string]*resources.DatabaseCatalog `json:"database_catalogs,omitempty"` + SyncedDatabaseTables map[string]*resources.SyncedDatabaseTable `json:"synced_database_tables,omitempty"` + PostgresProjects map[string]*resources.PostgresProject `json:"postgres_projects,omitempty"` + PostgresBranches map[string]*resources.PostgresBranch `json:"postgres_branches,omitempty"` + PostgresEndpoints map[string]*resources.PostgresEndpoint `json:"postgres_endpoints,omitempty"` + PostgresCatalogs map[string]*resources.PostgresCatalog `json:"postgres_catalogs,omitempty"` + PostgresDatabases map[string]*resources.PostgresDatabase `json:"postgres_databases,omitempty"` + PostgresRoles map[string]*resources.PostgresRole `json:"postgres_roles,omitempty"` + PostgresSyncedTables map[string]*resources.PostgresSyncedTable `json:"postgres_synced_tables,omitempty"` + PostgresSnapshotSchedules map[string]*resources.PostgresSnapshotSchedule `json:"postgres_snapshot_schedules,omitempty"` + VectorSearchEndpoints map[string]*resources.VectorSearchEndpoint `json:"vector_search_endpoints,omitempty"` + VectorSearchIndexes map[string]*resources.VectorSearchIndex `json:"vector_search_indexes,omitempty"` + InstancePools map[string]*resources.InstancePool `json:"instance_pools,omitempty"` + Secrets map[string]*resources.Secret `json:"secrets,omitempty"` + ClusterPolicies map[string]*resources.ClusterPolicy `json:"cluster_policies,omitempty"` } type ConfigResource interface { @@ -128,6 +129,7 @@ func (r *Resources) AllResources() []ResourceGroup { collectResourceMap(descriptions["postgres_databases"], r.PostgresDatabases), collectResourceMap(descriptions["postgres_roles"], r.PostgresRoles), collectResourceMap(descriptions["postgres_synced_tables"], r.PostgresSyncedTables), + collectResourceMap(descriptions["postgres_snapshot_schedules"], r.PostgresSnapshotSchedules), collectResourceMap(descriptions["vector_search_endpoints"], r.VectorSearchEndpoints), collectResourceMap(descriptions["vector_search_indexes"], r.VectorSearchIndexes), collectResourceMap(descriptions["instance_pools"], r.InstancePools), @@ -164,39 +166,40 @@ func (r *Resources) FindResourceByConfigKey(key string) (ConfigResource, error) // SupportedResources returns a map which keys correspond to the resource key in the bundle configuration. func SupportedResources() map[string]resources.ResourceDescription { return map[string]resources.ResourceDescription{ - "jobs": (&resources.Job{}).ResourceDescription(), - "job_runs": (&resources.JobRun{}).ResourceDescription(), - "pipelines": (&resources.Pipeline{}).ResourceDescription(), - "models": (&resources.MlflowModel{}).ResourceDescription(), - "experiments": (&resources.MlflowExperiment{}).ResourceDescription(), - "instance_pools": (&resources.InstancePool{}).ResourceDescription(), - "model_serving_endpoints": (&resources.ModelServingEndpoint{}).ResourceDescription(), - "registered_models": (&resources.RegisteredModel{}).ResourceDescription(), - "quality_monitors": (&resources.QualityMonitor{}).ResourceDescription(), - "catalogs": (&resources.Catalog{}).ResourceDescription(), - "schemas": (&resources.Schema{}).ResourceDescription(), - "external_locations": (&resources.ExternalLocation{}).ResourceDescription(), - "clusters": (&resources.Cluster{}).ResourceDescription(), - "dashboards": (&resources.Dashboard{}).ResourceDescription(), - "genie_spaces": (&resources.GenieSpace{}).ResourceDescription(), - "volumes": (&resources.Volume{}).ResourceDescription(), - "apps": (&resources.App{}).ResourceDescription(), - "secret_scopes": (&resources.SecretScope{}).ResourceDescription(), - "alerts": (&resources.Alert{}).ResourceDescription(), - "sql_warehouses": (&resources.SqlWarehouse{}).ResourceDescription(), - "database_instances": (&resources.DatabaseInstance{}).ResourceDescription(), - "database_catalogs": (&resources.DatabaseCatalog{}).ResourceDescription(), - "synced_database_tables": (&resources.SyncedDatabaseTable{}).ResourceDescription(), - "postgres_projects": (&resources.PostgresProject{}).ResourceDescription(), - "postgres_branches": (&resources.PostgresBranch{}).ResourceDescription(), - "postgres_endpoints": (&resources.PostgresEndpoint{}).ResourceDescription(), - "postgres_catalogs": (&resources.PostgresCatalog{}).ResourceDescription(), - "postgres_databases": (&resources.PostgresDatabase{}).ResourceDescription(), - "postgres_roles": (&resources.PostgresRole{}).ResourceDescription(), - "postgres_synced_tables": (&resources.PostgresSyncedTable{}).ResourceDescription(), - "vector_search_endpoints": (&resources.VectorSearchEndpoint{}).ResourceDescription(), - "vector_search_indexes": (&resources.VectorSearchIndex{}).ResourceDescription(), - "secrets": (&resources.Secret{}).ResourceDescription(), - "cluster_policies": (&resources.ClusterPolicy{}).ResourceDescription(), + "jobs": (&resources.Job{}).ResourceDescription(), + "job_runs": (&resources.JobRun{}).ResourceDescription(), + "pipelines": (&resources.Pipeline{}).ResourceDescription(), + "models": (&resources.MlflowModel{}).ResourceDescription(), + "experiments": (&resources.MlflowExperiment{}).ResourceDescription(), + "instance_pools": (&resources.InstancePool{}).ResourceDescription(), + "model_serving_endpoints": (&resources.ModelServingEndpoint{}).ResourceDescription(), + "registered_models": (&resources.RegisteredModel{}).ResourceDescription(), + "quality_monitors": (&resources.QualityMonitor{}).ResourceDescription(), + "catalogs": (&resources.Catalog{}).ResourceDescription(), + "schemas": (&resources.Schema{}).ResourceDescription(), + "external_locations": (&resources.ExternalLocation{}).ResourceDescription(), + "clusters": (&resources.Cluster{}).ResourceDescription(), + "dashboards": (&resources.Dashboard{}).ResourceDescription(), + "genie_spaces": (&resources.GenieSpace{}).ResourceDescription(), + "volumes": (&resources.Volume{}).ResourceDescription(), + "apps": (&resources.App{}).ResourceDescription(), + "secret_scopes": (&resources.SecretScope{}).ResourceDescription(), + "alerts": (&resources.Alert{}).ResourceDescription(), + "sql_warehouses": (&resources.SqlWarehouse{}).ResourceDescription(), + "database_instances": (&resources.DatabaseInstance{}).ResourceDescription(), + "database_catalogs": (&resources.DatabaseCatalog{}).ResourceDescription(), + "synced_database_tables": (&resources.SyncedDatabaseTable{}).ResourceDescription(), + "postgres_projects": (&resources.PostgresProject{}).ResourceDescription(), + "postgres_branches": (&resources.PostgresBranch{}).ResourceDescription(), + "postgres_endpoints": (&resources.PostgresEndpoint{}).ResourceDescription(), + "postgres_catalogs": (&resources.PostgresCatalog{}).ResourceDescription(), + "postgres_databases": (&resources.PostgresDatabase{}).ResourceDescription(), + "postgres_roles": (&resources.PostgresRole{}).ResourceDescription(), + "postgres_synced_tables": (&resources.PostgresSyncedTable{}).ResourceDescription(), + "postgres_snapshot_schedules": (&resources.PostgresSnapshotSchedule{}).ResourceDescription(), + "vector_search_endpoints": (&resources.VectorSearchEndpoint{}).ResourceDescription(), + "vector_search_indexes": (&resources.VectorSearchIndex{}).ResourceDescription(), + "secrets": (&resources.Secret{}).ResourceDescription(), + "cluster_policies": (&resources.ClusterPolicy{}).ResourceDescription(), } } diff --git a/bundle/config/resources/postgres_snapshot_schedule.go b/bundle/config/resources/postgres_snapshot_schedule.go new file mode 100644 index 00000000000..374aa55f355 --- /dev/null +++ b/bundle/config/resources/postgres_snapshot_schedule.go @@ -0,0 +1,73 @@ +package resources + +import ( + "context" + "net/url" + + "github.com/databricks/cli/libs/log" + "github.com/databricks/databricks-sdk-go" + "github.com/databricks/databricks-sdk-go/marshal" + "github.com/databricks/databricks-sdk-go/service/postgres" +) + +type PostgresSnapshotScheduleConfig struct { + // Branch is the branch whose automatic-snapshot schedule this resource manages. + // Format: "projects/{project_id}/branches/{branch_id}". The schedule's resource + // name (and this resource's ID) is "{branch}/snapshot-schedule". + Branch string `json:"branch"` + + // Schedule is the set of cadences at which automatic snapshots are taken. An + // empty set disables automatic snapshots. Order is not significant; when + // several cadences fire together a single snapshot is taken, retained for the + // longest of their retentions. + Schedule []postgres.ScheduleCadence `json:"schedule,omitempty"` + + // ForceSendFields tracks zero-value top-level fields (branch) for the SDK's + // marshal package. + ForceSendFields []string `json:"-" url:"-"` +} + +func (c *PostgresSnapshotScheduleConfig) UnmarshalJSON(b []byte) error { + return marshal.Unmarshal(b, c) +} + +func (c *PostgresSnapshotScheduleConfig) MarshalJSON() ([]byte, error) { + return marshal.Marshal(c) +} + +type PostgresSnapshotSchedule struct { + BaseResource + PostgresSnapshotScheduleConfig +} + +func (b *PostgresSnapshotSchedule) Exists(ctx context.Context, w *databricks.WorkspaceClient, name string) (bool, error) { + _, err := w.Postgres.GetSnapshotSchedule(ctx, postgres.GetSnapshotScheduleRequest{Name: name}) + if err != nil { + log.Debugf(ctx, "postgres snapshot schedule %s does not exist", name) + return false, err + } + return true, nil +} + +func (b *PostgresSnapshotSchedule) ResourceDescription() ResourceDescription { + return ResourceDescription{ + SingularName: "postgres_snapshot_schedule", + PluralName: "postgres_snapshot_schedules", + SingularTitle: "Postgres snapshot schedule", + PluralTitle: "Postgres snapshot schedules", + } +} + +func (b *PostgresSnapshotSchedule) GetName() string { + // Snapshot schedules don't have a user-visible name field. + return "" +} + +func (b *PostgresSnapshotSchedule) GetURL() string { + // The IDs in the API do not (yet) map to IDs in the web UI. + return "" +} + +func (b *PostgresSnapshotSchedule) InitializeURL(_ url.URL) { + // The IDs in the API do not (yet) map to IDs in the web UI. +} diff --git a/bundle/config/resources_test.go b/bundle/config/resources_test.go index 7e56f47a64a..dfef773ff88 100644 --- a/bundle/config/resources_test.go +++ b/bundle/config/resources_test.go @@ -128,13 +128,14 @@ func TestBundleResourcePluralNamesResolveInWorkspaceURLs(t *testing.T) { // A job run does have a workspace URL, but it's addressed by two IDs // (job + run) so it can't be expressed as a single-ID pattern here; it's // built in JobRun.InitializeURL via workspaceurls.JobRunURL instead. - "job_runs": true, - "postgres_branches": true, - "postgres_databases": true, - "postgres_endpoints": true, - "postgres_projects": true, - "postgres_roles": true, - "secret_scopes": true, + "job_runs": true, + "postgres_branches": true, + "postgres_databases": true, + "postgres_endpoints": true, + "postgres_projects": true, + "postgres_roles": true, + "postgres_snapshot_schedules": true, + "secret_scopes": true, } supported := SupportedResources() @@ -334,6 +335,13 @@ func TestResourcesBindSupport(t *testing.T) { }, }, }, + PostgresSnapshotSchedules: map[string]*resources.PostgresSnapshotSchedule{ + "my_postgres_snapshot_schedule": { + PostgresSnapshotScheduleConfig: resources.PostgresSnapshotScheduleConfig{ + Branch: "projects/my-postgres-project/branches/my-postgres-branch", + }, + }, + }, VectorSearchEndpoints: map[string]*resources.VectorSearchEndpoint{ "my_vector_search_endpoint": { CreateEndpoint: vectorsearch.CreateEndpoint{ @@ -391,6 +399,7 @@ func TestResourcesBindSupport(t *testing.T) { m.GetMockPostgresAPI().EXPECT().GetDatabase(mock.Anything, mock.Anything).Return(nil, nil) m.GetMockPostgresAPI().EXPECT().GetRole(mock.Anything, mock.Anything).Return(nil, nil) m.GetMockPostgresAPI().EXPECT().GetSyncedTable(mock.Anything, mock.Anything).Return(nil, nil) + m.GetMockPostgresAPI().EXPECT().GetSnapshotSchedule(mock.Anything, mock.Anything).Return(nil, nil) m.GetMockPostgresAPI().EXPECT().GetRole(mock.Anything, mock.Anything).Return(nil, nil) m.GetMockVectorSearchEndpointsAPI().EXPECT().GetEndpoint(mock.Anything, mock.Anything).Return(nil, nil) m.GetMockVectorSearchIndexesAPI().EXPECT().GetIndexByIndexName(mock.Anything, mock.Anything).Return(nil, nil) diff --git a/bundle/direct/dresources/all.go b/bundle/direct/dresources/all.go index 391fb0684d2..d482c8fb722 100644 --- a/bundle/direct/dresources/all.go +++ b/bundle/direct/dresources/all.go @@ -7,40 +7,41 @@ import ( ) var SupportedResources = map[string]any{ - "jobs": (*ResourceJob)(nil), - "job_runs": (*ResourceJobRun)(nil), - "pipelines": (*ResourcePipeline)(nil), - "experiments": (*ResourceExperiment)(nil), - "catalogs": (*ResourceCatalog)(nil), - "schemas": (*ResourceSchema)(nil), - "external_locations": (*ResourceExternalLocation)(nil), - "volumes": (*ResourceVolume)(nil), - "models": (*ResourceMlflowModel)(nil), - "apps": (*ResourceApp)(nil), - "sql_warehouses": (*ResourceSqlWarehouse)(nil), - "database_instances": (*ResourceDatabaseInstance)(nil), - "database_catalogs": (*ResourceDatabaseCatalog)(nil), - "synced_database_tables": (*ResourceSyncedDatabaseTable)(nil), - "postgres_projects": (*ResourcePostgresProject)(nil), - "postgres_branches": (*ResourcePostgresBranch)(nil), - "postgres_endpoints": (*ResourcePostgresEndpoint)(nil), - "postgres_catalogs": (*ResourcePostgresCatalog)(nil), - "postgres_databases": (*ResourcePostgresDatabase)(nil), - "postgres_roles": (*ResourcePostgresRole)(nil), - "postgres_synced_tables": (*ResourcePostgresSyncedTable)(nil), - "alerts": (*ResourceAlert)(nil), - "clusters": (*ResourceCluster)(nil), - "registered_models": (*ResourceRegisteredModel)(nil), - "dashboards": (*ResourceDashboard)(nil), - "genie_spaces": (*ResourceGenieSpace)(nil), - "secret_scopes": (*ResourceSecretScope)(nil), - "model_serving_endpoints": (*ResourceModelServingEndpoint)(nil), - "quality_monitors": (*ResourceQualityMonitor)(nil), - "vector_search_endpoints": (*ResourceVectorSearchEndpoint)(nil), - "vector_search_indexes": (*ResourceVectorSearchIndex)(nil), - "instance_pools": (*ResourceInstancePool)(nil), - "secrets": (*ResourceSecret)(nil), - "cluster_policies": (*ResourceClusterPolicy)(nil), + "jobs": (*ResourceJob)(nil), + "job_runs": (*ResourceJobRun)(nil), + "pipelines": (*ResourcePipeline)(nil), + "experiments": (*ResourceExperiment)(nil), + "catalogs": (*ResourceCatalog)(nil), + "schemas": (*ResourceSchema)(nil), + "external_locations": (*ResourceExternalLocation)(nil), + "volumes": (*ResourceVolume)(nil), + "models": (*ResourceMlflowModel)(nil), + "apps": (*ResourceApp)(nil), + "sql_warehouses": (*ResourceSqlWarehouse)(nil), + "database_instances": (*ResourceDatabaseInstance)(nil), + "database_catalogs": (*ResourceDatabaseCatalog)(nil), + "synced_database_tables": (*ResourceSyncedDatabaseTable)(nil), + "postgres_projects": (*ResourcePostgresProject)(nil), + "postgres_branches": (*ResourcePostgresBranch)(nil), + "postgres_endpoints": (*ResourcePostgresEndpoint)(nil), + "postgres_catalogs": (*ResourcePostgresCatalog)(nil), + "postgres_databases": (*ResourcePostgresDatabase)(nil), + "postgres_roles": (*ResourcePostgresRole)(nil), + "postgres_synced_tables": (*ResourcePostgresSyncedTable)(nil), + "postgres_snapshot_schedules": (*ResourcePostgresSnapshotSchedule)(nil), + "alerts": (*ResourceAlert)(nil), + "clusters": (*ResourceCluster)(nil), + "registered_models": (*ResourceRegisteredModel)(nil), + "dashboards": (*ResourceDashboard)(nil), + "genie_spaces": (*ResourceGenieSpace)(nil), + "secret_scopes": (*ResourceSecretScope)(nil), + "model_serving_endpoints": (*ResourceModelServingEndpoint)(nil), + "quality_monitors": (*ResourceQualityMonitor)(nil), + "vector_search_endpoints": (*ResourceVectorSearchEndpoint)(nil), + "vector_search_indexes": (*ResourceVectorSearchIndex)(nil), + "instance_pools": (*ResourceInstancePool)(nil), + "secrets": (*ResourceSecret)(nil), + "cluster_policies": (*ResourceClusterPolicy)(nil), // Permissions "jobs.permissions": (*ResourcePermissions)(nil), diff --git a/bundle/direct/dresources/all_test.go b/bundle/direct/dresources/all_test.go index 36eaa3e27df..d385a8e7cdf 100644 --- a/bundle/direct/dresources/all_test.go +++ b/bundle/direct/dresources/all_test.go @@ -792,6 +792,38 @@ var testDeps = map[string]prepareWorkspace{ }, nil }, + "postgres_snapshot_schedules": func(ctx context.Context, client *databricks.WorkspaceClient) (any, error) { + // Create parent project first + _, err := client.Postgres.CreateProject(ctx, postgres.CreateProjectRequest{ + ProjectId: "test-project-for-snapshot-schedule", + Project: postgres.Project{ + Spec: &postgres.ProjectSpec{ + DisplayName: "Test Project for Snapshot Schedule", + PgVersion: 16, + }, + }, + }) + if err != nil { + return nil, err + } + + // Create parent branch + _, err = client.Postgres.CreateBranch(ctx, postgres.CreateBranchRequest{ + Parent: "projects/test-project-for-snapshot-schedule", + BranchId: "test-branch-for-snapshot-schedule", + Branch: postgres.Branch{}, + }) + if err != nil { + return nil, err + } + + return &resources.PostgresSnapshotSchedule{ + PostgresSnapshotScheduleConfig: resources.PostgresSnapshotScheduleConfig{ + Branch: "projects/test-project-for-snapshot-schedule/branches/test-branch-for-snapshot-schedule", + }, + }, nil + }, + "postgres_endpoints": func(ctx context.Context, client *databricks.WorkspaceClient) (any, error) { // Create parent project first _, err := client.Postgres.CreateProject(ctx, postgres.CreateProjectRequest{ @@ -1129,7 +1161,10 @@ func testCRUD(t *testing.T, group string, adapter *Adapter, client *databricks.W require.NoError(t, err) } - deleteIsNoop := strings.HasSuffix(group, "permissions") || strings.HasSuffix(group, "grants") + // postgres_snapshot_schedules has no delete endpoint: DoDelete disables the + // schedule by setting an empty cadence set, and the schedule remains readable + // (it is intrinsic to the branch), so DoRead still succeeds afterwards. + deleteIsNoop := strings.HasSuffix(group, "permissions") || strings.HasSuffix(group, "grants") || group == "postgres_snapshot_schedules" // Apps DoDelete is fire-and-forget: the API returns success while the app // sits in DELETING state for up to ~20 minutes before the record is removed. // A GET on the DELETING app returns the app, not 404 -- the testserver diff --git a/bundle/direct/dresources/postgres_snapshot_schedule.go b/bundle/direct/dresources/postgres_snapshot_schedule.go new file mode 100644 index 00000000000..ff01bdba1d7 --- /dev/null +++ b/bundle/direct/dresources/postgres_snapshot_schedule.go @@ -0,0 +1,131 @@ +package dresources + +import ( + "context" + "strings" + + "github.com/databricks/cli/bundle/config/resources" + "github.com/databricks/databricks-sdk-go" + "github.com/databricks/databricks-sdk-go/common/types/fieldmask" + "github.com/databricks/databricks-sdk-go/marshal" + "github.com/databricks/databricks-sdk-go/service/postgres" +) + +// snapshotScheduleSuffix is the final segment of a snapshot schedule's resource +// name: "projects/{project_id}/branches/{branch_id}/snapshot-schedule". +const snapshotScheduleSuffix = "/snapshot-schedule" + +// PostgresSnapshotScheduleRemote is the return type for DoRead. It carries all +// paths present in StateType (branch, schedule) so drift detection works, plus +// the schedule's resource name. +type PostgresSnapshotScheduleRemote struct { + Branch string `json:"branch,omitempty"` + Schedule []postgres.ScheduleCadence `json:"schedule,omitempty"` + Name string `json:"name,omitempty"` +} + +func (s *PostgresSnapshotScheduleRemote) UnmarshalJSON(b []byte) error { + return marshal.Unmarshal(b, s) +} + +func (s PostgresSnapshotScheduleRemote) MarshalJSON() ([]byte, error) { + return marshal.Marshal(s) +} + +type ResourcePostgresSnapshotSchedule struct { + client *databricks.WorkspaceClient +} + +type PostgresSnapshotScheduleState = resources.PostgresSnapshotScheduleConfig + +func (*ResourcePostgresSnapshotSchedule) New(client *databricks.WorkspaceClient) *ResourcePostgresSnapshotSchedule { + return &ResourcePostgresSnapshotSchedule{client: client} +} + +func (*ResourcePostgresSnapshotSchedule) PrepareState(input *resources.PostgresSnapshotSchedule) *PostgresSnapshotScheduleState { + return &PostgresSnapshotScheduleState{ + Branch: input.Branch, + Schedule: input.Schedule, + ForceSendFields: input.ForceSendFields, + } +} + +func (*ResourcePostgresSnapshotSchedule) RemapState(remote *PostgresSnapshotScheduleRemote) *PostgresSnapshotScheduleState { + return &PostgresSnapshotScheduleState{ + Branch: remote.Branch, + Schedule: remote.Schedule, + ForceSendFields: nil, + } +} + +// makePostgresSnapshotScheduleRemote converts the SDK SnapshotSchedule into the +// remote shape. The API addresses the schedule by "{branch}/snapshot-schedule"; +// branch is derived by stripping that suffix so it participates in drift detection. +func makePostgresSnapshotScheduleRemote(schedule *postgres.SnapshotSchedule) *PostgresSnapshotScheduleRemote { + return &PostgresSnapshotScheduleRemote{ + Branch: strings.TrimSuffix(schedule.Name, snapshotScheduleSuffix), + Schedule: schedule.Schedule, + Name: schedule.Name, + } +} + +func (r *ResourcePostgresSnapshotSchedule) DoRead(ctx context.Context, id string) (*PostgresSnapshotScheduleRemote, error) { + schedule, err := r.client.Postgres.GetSnapshotSchedule(ctx, postgres.GetSnapshotScheduleRequest{Name: id}) + if err != nil { + return nil, err + } + return makePostgresSnapshotScheduleRemote(schedule), nil +} + +// updateSnapshotSchedule sets the branch's schedule to the given cadences and +// waits for the long-running operation to complete. It is the single API call +// behind create, update, and delete: there is no Create/DeleteSnapshotSchedule +// endpoint, so the schedule is managed entirely through UpdateSnapshotSchedule. +// schedule is the only updatable path, so a static mask is used. +func (r *ResourcePostgresSnapshotSchedule) updateSnapshotSchedule(ctx context.Context, name string, cadences []postgres.ScheduleCadence) (*postgres.SnapshotSchedule, error) { + waiter, err := r.client.Postgres.UpdateSnapshotSchedule(ctx, postgres.UpdateSnapshotScheduleRequest{ + Name: name, + SnapshotSchedule: postgres.SnapshotSchedule{ + Schedule: cadences, + + // Name is carried in the request's Name field, not the body. + Name: "", + ForceSendFields: nil, + }, + UpdateMask: fieldmask.FieldMask{ + Paths: []string{"schedule"}, + }, + }) + if err != nil { + return nil, err + } + return waiter.Wait(ctx) +} + +func (r *ResourcePostgresSnapshotSchedule) DoCreate(ctx context.Context, config *PostgresSnapshotScheduleState) (string, *PostgresSnapshotScheduleRemote, error) { + // The schedule exists implicitly for every branch; "creating" the resource + // means setting its cadences via UpdateSnapshotSchedule. + result, err := r.updateSnapshotSchedule(ctx, config.Branch+snapshotScheduleSuffix, config.Schedule) + if err != nil { + return "", nil, err + } + remote := makePostgresSnapshotScheduleRemote(result) + return remote.Name, remote, nil +} + +func (r *ResourcePostgresSnapshotSchedule) DoUpdate(ctx context.Context, id string, config *PostgresSnapshotScheduleState, _ *PlanEntry) (*PostgresSnapshotScheduleRemote, error) { + result, err := r.updateSnapshotSchedule(ctx, id, config.Schedule) + if err != nil { + return nil, err + } + return makePostgresSnapshotScheduleRemote(result), nil +} + +func (r *ResourcePostgresSnapshotSchedule) DoDelete(ctx context.Context, id string, _ *PostgresSnapshotScheduleState) error { + // There is no DeleteSnapshotSchedule endpoint. DoDelete fires whenever the + // resource leaves the desired state (removed from config, or bundle destroy), + // so disable automatic snapshots by setting an empty cadence set — otherwise + // the branch would keep taking snapshots after the resource is gone. + _, err := r.updateSnapshotSchedule(ctx, id, nil) + return err +} diff --git a/bundle/direct/dresources/resources.yml b/bundle/direct/dresources/resources.yml index 07eab3b6894..bfbc956bd1d 100644 --- a/bundle/direct/dresources/resources.yml +++ b/bundle/direct/dresources/resources.yml @@ -789,6 +789,14 @@ resources: - field: identity_type reason: immutable + postgres_snapshot_schedules: + provided_id_fields: + # branch composes the schedule's hierarchical name + # ("{branch}/snapshot-schedule"); changing it targets a different branch's + # schedule, so it recreates (delete + create). + - field: branch + reason: id_field + vector_search_endpoints: provided_id_fields: # The endpoint API has no rename; the endpoint is fetched by name. diff --git a/bundle/internal/schema/annotations.yml b/bundle/internal/schema/annotations.yml index e47f89c505a..5de96889db9 100644 --- a/bundle/internal/schema/annotations.yml +++ b/bundle/internal/schema/annotations.yml @@ -1575,6 +1575,19 @@ resources: "role_id": "description": |- The user-specified role ID; becomes the final component of the role's resource name. Must be 4-63 characters, lowercase letters, numbers, and hyphens (RFC 1123). + "postgres_snapshot_schedules": + "description": |- + The Postgres snapshot schedule definitions for the bundle, where each key is the name of the snapshot schedule. Each entry configures the automatic-snapshot cadences for a branch of a Lakebase Autoscaling project. + "$fields": + "branch": + "description": |- + The branch whose automatic-snapshot schedule this manages. Format: projects/{project_id}/branches/{branch_id} + "lifecycle": + "description": |- + Settings that control the deployment lifecycle of the resource, such as preventing it from being destroyed. + "schedule": + "description": |- + The cadences at which automatic snapshots are taken. An empty set disables automatic snapshots. When several cadences fire together, one snapshot is taken and retained for the longest of their retentions. "postgres_synced_tables": "description": |- The Postgres synced table definitions for the bundle, where each key is the name of the synced table. Each entry continuously replicates a Unity Catalog Delta source table into a Postgres table on a Lakebase Autoscaling instance. diff --git a/bundle/schema/jsonschema.json b/bundle/schema/jsonschema.json index 5967696cb91..ec77bff0bf3 100644 --- a/bundle/schema/jsonschema.json +++ b/bundle/schema/jsonschema.json @@ -2268,6 +2268,35 @@ } ] }, + "resources.PostgresSnapshotSchedule": { + "oneOf": [ + { + "type": "object", + "properties": { + "branch": { + "description": "The branch whose automatic-snapshot schedule this manages. Format: projects/{project_id}/branches/{branch_id}", + "$ref": "#/$defs/string" + }, + "lifecycle": { + "description": "Settings that control the deployment lifecycle of the resource, such as preventing it from being destroyed.", + "$ref": "#/$defs/github.com/databricks/cli/bundle/config/resources.Lifecycle" + }, + "schedule": { + "description": "The cadences at which automatic snapshots are taken. An empty set disables automatic snapshots. When several cadences fire together, one snapshot is taken and retained for the longest of their retentions.", + "$ref": "#/$defs/slice/github.com/databricks/databricks-sdk-go/service/postgres.ScheduleCadence" + } + }, + "additionalProperties": false, + "required": [ + "branch" + ] + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\._*\\p{L}+([-_]*[\\p{L}\\p{N}]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] + }, "resources.PostgresSyncedTable": { "oneOf": [ { @@ -3581,6 +3610,10 @@ "description": "The Postgres role definitions for the bundle, where each key is the name of the role. Each entry defines a role on a Lakebase Autoscaling branch, optionally backed by a Databricks identity.", "$ref": "#/$defs/map/github.com/databricks/cli/bundle/config/resources.PostgresRole" }, + "postgres_snapshot_schedules": { + "description": "The Postgres snapshot schedule definitions for the bundle, where each key is the name of the snapshot schedule. Each entry configures the automatic-snapshot cadences for a branch of a Lakebase Autoscaling project.", + "$ref": "#/$defs/map/github.com/databricks/cli/bundle/config/resources.PostgresSnapshotSchedule" + }, "postgres_synced_tables": { "description": "The Postgres synced table definitions for the bundle, where each key is the name of the synced table. Each entry continuously replicates a Unity Catalog Delta source table into a Postgres table on a Lakebase Autoscaling instance.", "$ref": "#/$defs/map/github.com/databricks/cli/bundle/config/resources.PostgresSyncedTable" @@ -12736,6 +12769,57 @@ } ] }, + "postgres.DailySchedule": { + "oneOf": [ + { + "type": "object", + "description": "Take a snapshot once per day, at the configured hour.", + "properties": { + "hour": { + "description": "[Private Preview] The hour of the day, in UTC, at which to take the snapshot, in [0, 23].", + "$ref": "#/$defs/int", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + } + }, + "additionalProperties": false + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\._*\\p{L}+([-_]*[\\p{L}\\p{N}]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] + }, + "postgres.DayOfWeek": { + "oneOf": [ + { + "type": "string", + "description": "The day of the week on which a weekly snapshot is taken.", + "enum": [ + "MONDAY", + "TUESDAY", + "WEDNESDAY", + "THURSDAY", + "FRIDAY", + "SATURDAY", + "SUNDAY" + ], + "enumDescriptions": [ + "[Private Preview]", + "[Private Preview]", + "[Private Preview]", + "[Private Preview]", + "[Private Preview]", + "[Private Preview]", + "[Private Preview]" + ] + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\._*\\p{L}+([-_]*[\\p{L}\\p{N}]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] + }, "postgres.EndpointGroupSpec": { "oneOf": [ { @@ -12801,6 +12885,36 @@ } ] }, + "postgres.MonthlySchedule": { + "oneOf": [ + { + "type": "object", + "description": "Take a snapshot once per month, on the configured day at the configured hour.", + "properties": { + "day": { + "description": "[Private Preview] The day of the month on which to take the snapshot, in [1, 31]. In shorter\nmonths the snapshot is taken on the last day instead (day 31 runs on Feb 28\nor 29, and on Apr 30), so every month gets exactly one snapshot.", + "$ref": "#/$defs/int", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + }, + "hour": { + "description": "[Private Preview] The hour of the day, in UTC, at which to take the snapshot, in [0, 23].", + "$ref": "#/$defs/int", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + } + }, + "additionalProperties": false, + "required": [ + "day" + ] + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\._*\\p{L}+([-_]*[\\p{L}\\p{N}]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] + }, "postgres.NewPipelineSpec": { "oneOf": [ { @@ -12986,6 +13100,48 @@ } ] }, + "postgres.ScheduleCadence": { + "oneOf": [ + { + "type": "object", + "description": "One cadence at which automatic snapshots are taken.", + "properties": { + "daily_schedule": { + "description": "[Private Preview] Take a snapshot once per day.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/postgres.DailySchedule", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + }, + "monthly_schedule": { + "description": "[Private Preview] Take a snapshot once per month.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/postgres.MonthlySchedule", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + }, + "retention": { + "description": "[Private Preview] How long snapshots from this cadence are kept before automatic deletion.\nMust be at least 1 hour. Applied when a snapshot is taken; not retroactive,\nso changing it affects only later snapshots.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/common/types/duration.Duration", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + }, + "weekly_schedule": { + "description": "[Private Preview] Take a snapshot once per week.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/postgres.WeeklySchedule", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + } + }, + "additionalProperties": false, + "required": [ + "retention" + ] + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\._*\\p{L}+([-_]*[\\p{L}\\p{N}]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] + }, "postgres.SyncedTableSyncedTableSpecExtraColumn": { "oneOf": [ { @@ -13112,6 +13268,36 @@ } ] }, + "postgres.WeeklySchedule": { + "oneOf": [ + { + "type": "object", + "description": "Take a snapshot once per week, on the configured day at the configured hour.", + "properties": { + "day_of_week": { + "description": "[Private Preview] The day of the week on which to take the snapshot.", + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/postgres.DayOfWeek", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + }, + "hour": { + "description": "[Private Preview] The hour of the day, in UTC, at which to take the snapshot, in [0, 23].", + "$ref": "#/$defs/int", + "x-databricks-launch-stage": "PRIVATE_PREVIEW", + "doNotSuggest": true + } + }, + "additionalProperties": false, + "required": [ + "day_of_week" + ] + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\._*\\p{L}+([-_]*[\\p{L}\\p{N}]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] + }, "serving.Ai21LabsConfig": { "oneOf": [ { @@ -15506,6 +15692,20 @@ } ] }, + "resources.PostgresSnapshotSchedule": { + "oneOf": [ + { + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/github.com/databricks/cli/bundle/config/resources.PostgresSnapshotSchedule" + } + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\._*\\p{L}+([-_]*[\\p{L}\\p{N}]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] + }, "resources.PostgresSyncedTable": { "oneOf": [ { @@ -16573,6 +16773,20 @@ } ] }, + "postgres.ScheduleCadence": { + "oneOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/github.com/databricks/databricks-sdk-go/service/postgres.ScheduleCadence" + } + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\._*\\p{L}+([-_]*[\\p{L}\\p{N}]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] + }, "postgres.SyncedTableSyncedTableSpecExtraColumn": { "oneOf": [ { diff --git a/libs/testserver/fake_workspace.go b/libs/testserver/fake_workspace.go index 2f077b1b631..d840a8beae2 100644 --- a/libs/testserver/fake_workspace.go +++ b/libs/testserver/fake_workspace.go @@ -229,14 +229,15 @@ type FakeWorkspace struct { DatabaseCatalogs map[string]database.DatabaseCatalog SyncedDatabaseTables map[string]database.SyncedDatabaseTable - PostgresProjects map[string]postgres.Project - PostgresBranches map[string]postgres.Branch - PostgresCatalogs map[string]postgres.Catalog - PostgresDatabases map[string]postgres.Database - PostgresEndpoints map[string]postgres.Endpoint - PostgresRoles map[string]postgres.Role - PostgresSyncedTables map[string]postgres.SyncedTable - PostgresOperations map[string]postgres.Operation + PostgresProjects map[string]postgres.Project + PostgresBranches map[string]postgres.Branch + PostgresCatalogs map[string]postgres.Catalog + PostgresDatabases map[string]postgres.Database + PostgresEndpoints map[string]postgres.Endpoint + PostgresRoles map[string]postgres.Role + PostgresSyncedTables map[string]postgres.SyncedTable + PostgresSnapshotSchedules map[string]postgres.SnapshotSchedule + PostgresOperations map[string]postgres.Operation // Branches and endpoints that the server provisioned implicitly together // with their parent (e.g. the production branch on a new project, or the @@ -492,6 +493,7 @@ func NewFakeWorkspace(url, token string) *FakeWorkspace { PostgresEndpoints: map[string]postgres.Endpoint{}, PostgresRoles: map[string]postgres.Role{}, PostgresSyncedTables: map[string]postgres.SyncedTable{}, + PostgresSnapshotSchedules: map[string]postgres.SnapshotSchedule{}, PostgresOperations: map[string]postgres.Operation{}, postgresImplicitBranches: map[string]bool{}, postgresImplicitEndpoints: map[string]bool{}, diff --git a/libs/testserver/handlers.go b/libs/testserver/handlers.go index 8c44d97eae7..8fe25f2b4c5 100644 --- a/libs/testserver/handlers.go +++ b/libs/testserver/handlers.go @@ -1089,6 +1089,11 @@ func AddDefaultHandlers(server *Server) { return req.Workspace.PostgresOperationGet(name) }) + server.Handle("GET", "/api/2.0/postgres/projects/{project_id}/branches/{branch_id}/snapshot-schedule/operations/{operation_id}", func(req Request) any { + name := "projects/" + req.Vars["project_id"] + "/branches/" + req.Vars["branch_id"] + "/snapshot-schedule/operations/" + req.Vars["operation_id"] + return req.Workspace.PostgresOperationGet(name) + }) + // Postgres Projects: server.Handle("POST", "/api/2.0/postgres/projects", func(req Request) any { projectID := req.URL.Query().Get("project_id") @@ -1142,6 +1147,17 @@ func AddDefaultHandlers(server *Server) { return req.Workspace.PostgresBranchDelete(name) }) + // Postgres Snapshot Schedules (a per-branch singleton; no create/delete): + server.Handle("GET", "/api/2.0/postgres/projects/{project_id}/branches/{branch_id}/snapshot-schedule", func(req Request) any { + name := "projects/" + req.Vars["project_id"] + "/branches/" + req.Vars["branch_id"] + "/snapshot-schedule" + return req.Workspace.PostgresSnapshotScheduleGet(name) + }) + + server.Handle("PATCH", "/api/2.0/postgres/projects/{project_id}/branches/{branch_id}/snapshot-schedule", func(req Request) any { + name := "projects/" + req.Vars["project_id"] + "/branches/" + req.Vars["branch_id"] + "/snapshot-schedule" + return req.Workspace.PostgresSnapshotScheduleUpdate(req, name) + }) + // Postgres Endpoints: server.Handle("POST", "/api/2.0/postgres/projects/{project_id}/branches/{branch_id}/endpoints", func(req Request) any { parent := "projects/" + req.Vars["project_id"] + "/branches/" + req.Vars["branch_id"] diff --git a/libs/testserver/postgres.go b/libs/testserver/postgres.go index ebc402fce07..d2e9c541567 100644 --- a/libs/testserver/postgres.go +++ b/libs/testserver/postgres.go @@ -516,6 +516,65 @@ func (s *FakeWorkspace) PostgresBranchDelete(name string) Response { } } +var snapshotScheduleUpdateMaskPaths = []string{"schedule"} + +// PostgresSnapshotScheduleGet retrieves a branch's snapshot schedule. The +// schedule is intrinsic to the branch: for a branch that never had one set, the +// API returns an empty schedule rather than 404, so the fake mirrors that. +func (s *FakeWorkspace) PostgresSnapshotScheduleGet(name string) Response { + defer s.LockUnlock()() + + branchName := strings.TrimSuffix(name, "/snapshot-schedule") + if _, exists := s.PostgresBranches[branchName]; !exists { + return postgresNotFoundResponse("branch") + } + + schedule, exists := s.PostgresSnapshotSchedules[name] + if !exists { + schedule = postgres.SnapshotSchedule{Name: name} + } + + return Response{ + Body: schedule, + } +} + +// PostgresSnapshotScheduleUpdate sets a branch's snapshot schedule. There is no +// create/delete endpoint; the schedule is managed entirely through this update. +// An empty schedule set disables automatic snapshots. +func (s *FakeWorkspace) PostgresSnapshotScheduleUpdate(req Request, name string) Response { + if resp := validateUpdateMask(req, snapshotScheduleUpdateMaskPaths); resp != nil { + return *resp + } + + defer s.LockUnlock()() + + branchName := strings.TrimSuffix(name, "/snapshot-schedule") + if _, exists := s.PostgresBranches[branchName]; !exists { + return postgresNotFoundResponse("branch") + } + + var updateSchedule postgres.SnapshotSchedule + if len(req.Body) > 0 { + if err := json.Unmarshal(req.Body, &updateSchedule); err != nil { + return Response{ + StatusCode: 400, + Body: fmt.Sprintf("cannot unmarshal request body: %v", err), + } + } + } + + schedule := postgres.SnapshotSchedule{ + Name: name, + Schedule: updateSchedule.Schedule, + } + s.PostgresSnapshotSchedules[name] = schedule + + return Response{ + Body: s.createOperationLocked(name, schedule), + } +} + // PostgresEndpointCreate creates a new postgres endpoint. // // When replaceExisting is true, an existing endpoint with the same ID is updated @@ -1472,6 +1531,8 @@ func (s *FakeWorkspace) createOperationLocked(resourceName string, response any) resourceType = "Catalog" case strings.HasPrefix(resourceName, "synced_tables/"): resourceType = "SyncedTable" + case strings.HasSuffix(resourceName, "/snapshot-schedule"): + resourceType = "SnapshotSchedule" case strings.Contains(resourceName, "/endpoints/"): resourceType = "Endpoint" case strings.Contains(resourceName, "/databases/"): From c57ed62a1dbb6b86bec5088c36cc92dffaec11a3 Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Tue, 1 Sep 2026 08:34:21 +0000 Subject: [PATCH 03/22] Remove redundant snapshot_schedules acceptance subtests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the `update` subtest (create/update/remove is already covered by `basic`) and the `orphaned` subtest (deleting a branch while keeping a schedule that references it is user error — it plans but fails at apply, which we don't need to pin in a golden). Co-authored-by: Isaac --- .../orphaned/databricks.yml.tmpl | 26 ----- .../orphaned/out.test.toml | 4 - .../orphaned/output.txt | 61 ------------ .../orphaned/script | 27 ------ .../update/databricks.yml.tmpl | 26 ----- .../update/out.requests.add.txt | 74 --------------- .../update/out.requests.remove.txt | 40 -------- .../update/out.test.toml | 4 - .../update/output.txt | 95 ------------------- .../postgres_snapshot_schedules/update/script | 28 ------ 10 files changed, 385 deletions(-) delete mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/databricks.yml.tmpl delete mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/out.test.toml delete mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/output.txt delete mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/script delete mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/update/databricks.yml.tmpl delete mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/update/out.requests.add.txt delete mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/update/out.requests.remove.txt delete mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/update/out.test.toml delete mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/update/output.txt delete mode 100644 acceptance/bundle/resources/postgres_snapshot_schedules/update/script diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/databricks.yml.tmpl b/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/databricks.yml.tmpl deleted file mode 100644 index f2ad5af11a6..00000000000 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/databricks.yml.tmpl +++ /dev/null @@ -1,26 +0,0 @@ -bundle: - name: deploy-pg-ss-orphaned-$UNIQUE_NAME - -sync: - paths: [] - -resources: - postgres_projects: - my_project: - project_id: test-pg-proj-$UNIQUE_NAME - display_name: "Test Project for Snapshot Schedules" - pg_version: 16 - - postgres_branches: - main: - parent: ${resources.postgres_projects.my_project.id} - branch_id: main - no_expiry: true - - postgres_snapshot_schedules: - main_schedule: - branch: ${resources.postgres_branches.main.id} - schedule: - - daily_schedule: - hour: 3 - retention: "604800s" diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/out.test.toml b/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/out.test.toml deleted file mode 100644 index 1314e661c24..00000000000 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/out.test.toml +++ /dev/null @@ -1,4 +0,0 @@ -Cloud = true -CloudEnvs.azure = false -CloudEnvs.gcp = false -EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/output.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/output.txt deleted file mode 100644 index 5cc6d36335e..00000000000 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/output.txt +++ /dev/null @@ -1,61 +0,0 @@ - -=== Deploy project + branch + snapshot schedule ->>> [CLI] bundle deploy -Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-orphaned-[UNIQUE_NAME]/default/files... -Created postgres_branches.main -Created postgres_projects.my_project -Created postgres_snapshot_schedules.main_schedule -Files: 0 uploaded, 0 deleted -Resources: 3 created, 0 changed, 0 deleted, 0 unchanged - -=== Remove the branch but keep the schedule that references it ->>> cat databricks.yml -bundle: - name: deploy-pg-ss-orphaned-[UNIQUE_NAME] - -sync: - paths: [] - -resources: - postgres_projects: - my_project: - project_id: test-pg-proj-[UNIQUE_NAME] - display_name: "Test Project for Snapshot Schedules" - pg_version: 16 - - postgres_snapshot_schedules: - main_schedule: - branch: ${resources.postgres_branches.main.id} - schedule: - - daily_schedule: - hour: 3 - retention: "604800s" -Name: deploy-pg-ss-orphaned-[UNIQUE_NAME] -Target: default -Workspace: - User: [USERNAME] - Path: /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-orphaned-[UNIQUE_NAME]/default - -Validation OK! -delete postgres_branches.main -recreate postgres_snapshot_schedules.main_schedule - -Plan: 1 to add, 0 to change, 2 to delete, 1 unchanged - ->>> [CLI] bundle destroy --auto-approve -The following resources will be deleted: - delete resources.postgres_branches.main - delete resources.postgres_projects.my_project - delete resources.postgres_snapshot_schedules.main_schedule - -This action will result in the deletion of the following Lakebase projects along with -all their branches, databases, and endpoints. All data stored in them will be permanently lost: - delete resources.postgres_projects.my_project - -This action will result in the deletion of the following Lakebase branches. -All data stored in them will be permanently lost: - delete resources.postgres_branches.main - -All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-orphaned-[UNIQUE_NAME]/default - -Destroy: 3 deleted diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/script b/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/script deleted file mode 100644 index f89a3ad4a87..00000000000 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/orphaned/script +++ /dev/null @@ -1,27 +0,0 @@ -cleanup() { - trace $CLI bundle destroy --auto-approve - rm -f out.requests.txt -} -trap cleanup EXIT - -title "Deploy project + branch + snapshot schedule" -envsubst < databricks.yml.tmpl > databricks.yml -trace $CLI bundle deploy - -# Remove ONLY the branch from config while keeping the snapshot schedule, which -# still references ${resources.postgres_branches.main.id}. The reference still -# resolves from the deployed state (the branch is present in state during the -# transition), so this does NOT fail as a dangling reference: validate passes and -# plan sequences a delete of the branch alongside a recreate of the schedule. -# Deploying that plan would fail at apply (the schedule cannot be created on a -# deleted branch); this test documents the plan-time behavior. Acceptable user -# error -- removing a parent while keeping a child that references it. -# errcode records the exit code so the outcome is captured deterministically. -title "Remove the branch but keep the schedule that references it" -sed '/^ postgres_branches:/,/^ postgres_snapshot_schedules:/{/^ postgres_snapshot_schedules:/!d}' databricks.yml > databricks.yml.new && mv databricks.yml.new databricks.yml -trace cat databricks.yml -errcode $CLI bundle validate -errcode $CLI bundle plan - -# Restore the full config so the destroy in cleanup can resolve references. -envsubst < databricks.yml.tmpl > databricks.yml diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/update/databricks.yml.tmpl b/acceptance/bundle/resources/postgres_snapshot_schedules/update/databricks.yml.tmpl deleted file mode 100644 index 0ea6ec13414..00000000000 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/update/databricks.yml.tmpl +++ /dev/null @@ -1,26 +0,0 @@ -bundle: - name: deploy-pg-ss-update-$UNIQUE_NAME - -sync: - paths: [] - -resources: - postgres_projects: - my_project: - project_id: test-pg-proj-$UNIQUE_NAME - display_name: "Test Project for Snapshot Schedules" - pg_version: 16 - - postgres_branches: - main: - parent: ${resources.postgres_projects.my_project.id} - branch_id: main - no_expiry: true - - postgres_snapshot_schedules: - main_schedule: - branch: ${resources.postgres_branches.main.id} - schedule: - - daily_schedule: - hour: 3 - retention: "604800s" diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.requests.add.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.requests.add.txt deleted file mode 100644 index 9c5f1edf5c9..00000000000 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.requests.add.txt +++ /dev/null @@ -1,74 +0,0 @@ -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" -} -{ - "method": "PATCH", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", - "q": { - "update_mask": "schedule" - }, - "body": { - "schedule": [ - { - "daily_schedule": { - "hour": 3 - }, - "retention": "604800s" - } - ] - } -} -{ - "method": "POST", - "path": "/api/2.0/postgres/projects", - "q": { - "project_id": "test-pg-proj-[UNIQUE_NAME]" - }, - "body": { - "spec": { - "display_name": "Test Project for Snapshot Schedules", - "pg_version": 16 - } - } -} -{ - "method": "POST", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches", - "q": { - "branch_id": "main" - }, - "body": { - "spec": { - "no_expiry": true - } - } -} diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.requests.remove.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.requests.remove.txt deleted file mode 100644 index bea13bc3b2a..00000000000 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.requests.remove.txt +++ /dev/null @@ -1,40 +0,0 @@ -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" -} -{ - "method": "PATCH", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", - "q": { - "update_mask": "schedule" - }, - "body": {} -} diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.test.toml b/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.test.toml deleted file mode 100644 index 1314e661c24..00000000000 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/update/out.test.toml +++ /dev/null @@ -1,4 +0,0 @@ -Cloud = true -CloudEnvs.azure = false -CloudEnvs.gcp = false -EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/update/output.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/update/output.txt deleted file mode 100644 index 1672fc03e07..00000000000 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/update/output.txt +++ /dev/null @@ -1,95 +0,0 @@ - -=== Deploy project + branch without a snapshot schedule ->>> cat databricks.yml -bundle: - name: deploy-pg-ss-update-[UNIQUE_NAME] - -sync: - paths: [] - -resources: - postgres_projects: - my_project: - project_id: test-pg-proj-[UNIQUE_NAME] - display_name: "Test Project for Snapshot Schedules" - pg_version: 16 - - postgres_branches: - main: - parent: ${resources.postgres_projects.my_project.id} - branch_id: main - no_expiry: true - - ->>> [CLI] bundle deploy -Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-update-[UNIQUE_NAME]/default/files... -Created postgres_branches.main -Created postgres_projects.my_project -Files: 0 uploaded, 0 deleted -Resources: 2 created, 0 changed, 0 deleted, 0 unchanged - ->>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule -{ - "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", - "schedule": null -} - -=== Add the snapshot schedule resource to the existing branch ->>> [CLI] bundle plan -create postgres_snapshot_schedules.main_schedule - -Plan: 1 to add, 0 to change, 0 to delete, 2 unchanged - ->>> [CLI] bundle deploy --auto-approve -Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-update-[UNIQUE_NAME]/default/files... -Created postgres_snapshot_schedules.main_schedule -Files: 0 uploaded, 0 deleted -Resources: 1 created, 0 changed, 0 deleted, 2 unchanged - ->>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule -{ - "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", - "schedule": [ - { - "daily_schedule": { - "hour": 3 - }, - "retention": "604800s" - } - ] -} - -=== Remove the snapshot schedule resource from the existing branch ->>> [CLI] bundle plan -delete postgres_snapshot_schedules.main_schedule - -Plan: 0 to add, 0 to change, 1 to delete, 2 unchanged - ->>> [CLI] bundle deploy --auto-approve -Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-update-[UNIQUE_NAME]/default/files... -Deleted postgres_snapshot_schedules.main_schedule -Files: 0 uploaded, 0 deleted -Resources: 0 created, 0 changed, 1 deleted, 2 unchanged - ->>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule -{ - "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", - "schedule": null -} - ->>> [CLI] bundle destroy --auto-approve -The following resources will be deleted: - delete resources.postgres_branches.main - delete resources.postgres_projects.my_project - -This action will result in the deletion of the following Lakebase projects along with -all their branches, databases, and endpoints. All data stored in them will be permanently lost: - delete resources.postgres_projects.my_project - -This action will result in the deletion of the following Lakebase branches. -All data stored in them will be permanently lost: - delete resources.postgres_branches.main - -All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-update-[UNIQUE_NAME]/default - -Destroy: 2 deleted diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/update/script b/acceptance/bundle/resources/postgres_snapshot_schedules/update/script deleted file mode 100644 index 6f69cc68102..00000000000 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/update/script +++ /dev/null @@ -1,28 +0,0 @@ -cleanup() { - trace $CLI bundle destroy --auto-approve - rm -f out.requests.txt -} -trap cleanup EXIT - -schedule_name="projects/test-pg-proj-${UNIQUE_NAME}/branches/main/snapshot-schedule" - -title "Deploy project + branch without a snapshot schedule" -envsubst < databricks.yml.tmpl | sed '/postgres_snapshot_schedules:/,$d' > databricks.yml -trace cat databricks.yml -rm -f out.requests.txt -trace $CLI bundle deploy -trace $CLI postgres get-snapshot-schedule "${schedule_name}" | snapshot_schedule_fields - -title "Add the snapshot schedule resource to the existing branch" -envsubst < databricks.yml.tmpl > databricks.yml -trace $CLI bundle plan -trace $CLI bundle deploy --auto-approve -trace $CLI postgres get-snapshot-schedule "${schedule_name}" | snapshot_schedule_fields -print_requests.py --del-body parent,project_id,branch_id --sort --get '//postgres' '^//workspace-files/' '^//workspace/' '^//telemetry-ext' '^//operations/' > out.requests.add.txt - -title "Remove the snapshot schedule resource from the existing branch" -sed '/postgres_snapshot_schedules:/,$d' databricks.yml > databricks.yml.new && mv databricks.yml.new databricks.yml -trace $CLI bundle plan -trace $CLI bundle deploy --auto-approve -trace $CLI postgres get-snapshot-schedule "${schedule_name}" | snapshot_schedule_fields -print_requests.py --del-body parent,project_id,branch_id --sort --get '//postgres' '^//workspace-files/' '^//workspace/' '^//telemetry-ext' '^//operations/' > out.requests.remove.txt From 48d3fa7a110d26c405f8be947bf9f220097dbc19 Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Tue, 1 Sep 2026 08:38:25 +0000 Subject: [PATCH 04/22] Add snapshotScheduleName helper to normalize a trailing slash DoCreate built the schedule resource name as `config.Branch + "/snapshot-schedule"`, which doubles the separator if a user writes `branch:` with a trailing slash. Route it through snapshotScheduleName, which trims trailing slashes first, and cover it with a unit test. Co-authored-by: Isaac --- .../dresources/postgres_snapshot_schedule.go | 9 ++++++++- .../postgres_snapshot_schedule_test.go | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 bundle/direct/dresources/postgres_snapshot_schedule_test.go diff --git a/bundle/direct/dresources/postgres_snapshot_schedule.go b/bundle/direct/dresources/postgres_snapshot_schedule.go index ff01bdba1d7..3f73e8c729f 100644 --- a/bundle/direct/dresources/postgres_snapshot_schedule.go +++ b/bundle/direct/dresources/postgres_snapshot_schedule.go @@ -15,6 +15,13 @@ import ( // name: "projects/{project_id}/branches/{branch_id}/snapshot-schedule". const snapshotScheduleSuffix = "/snapshot-schedule" +// snapshotScheduleName returns the schedule's resource name for a branch. It +// trims any trailing slash on the branch name (e.g. a user-supplied +// "projects/p/branches/b/") so the suffix is not doubled up. +func snapshotScheduleName(branch string) string { + return strings.TrimRight(branch, "/") + snapshotScheduleSuffix +} + // PostgresSnapshotScheduleRemote is the return type for DoRead. It carries all // paths present in StateType (branch, schedule) so drift detection works, plus // the schedule's resource name. @@ -105,7 +112,7 @@ func (r *ResourcePostgresSnapshotSchedule) updateSnapshotSchedule(ctx context.Co func (r *ResourcePostgresSnapshotSchedule) DoCreate(ctx context.Context, config *PostgresSnapshotScheduleState) (string, *PostgresSnapshotScheduleRemote, error) { // The schedule exists implicitly for every branch; "creating" the resource // means setting its cadences via UpdateSnapshotSchedule. - result, err := r.updateSnapshotSchedule(ctx, config.Branch+snapshotScheduleSuffix, config.Schedule) + result, err := r.updateSnapshotSchedule(ctx, snapshotScheduleName(config.Branch), config.Schedule) if err != nil { return "", nil, err } diff --git a/bundle/direct/dresources/postgres_snapshot_schedule_test.go b/bundle/direct/dresources/postgres_snapshot_schedule_test.go new file mode 100644 index 00000000000..261ceba17ad --- /dev/null +++ b/bundle/direct/dresources/postgres_snapshot_schedule_test.go @@ -0,0 +1,19 @@ +package dresources + +import "testing" + +func TestSnapshotScheduleName(t *testing.T) { + const branch = "projects/p/branches/b" + want := branch + "/snapshot-schedule" + + cases := []string{ + branch, + branch + "/", + branch + "//", + } + for _, in := range cases { + if got := snapshotScheduleName(in); got != want { + t.Errorf("snapshotScheduleName(%q) = %q, want %q", in, got, want) + } + } +} From 9970a2c30a95af88a26165e00d7f872e17fb197f Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Tue, 1 Sep 2026 08:44:44 +0000 Subject: [PATCH 05/22] Assert no drift after removing the snapshot schedule Add a `bundle plan` after the removal step in the basic acceptance test; it reports "0 to add, 0 to change, 0 to delete" (project and branch unchanged), confirming the disable settled cleanly and leaves no lingering drift. Co-authored-by: Isaac --- .../resources/postgres_snapshot_schedules/basic/output.txt | 4 ++++ .../bundle/resources/postgres_snapshot_schedules/basic/script | 3 +++ 2 files changed, 7 insertions(+) diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/output.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/output.txt index 1d39ab41bca..c7eff1ef484 100644 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/output.txt +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/output.txt @@ -75,6 +75,10 @@ Resources: 0 created, 0 changed, 1 deleted, 2 unchanged "schedule": null } +=== Plan again to confirm no drift after removal +>>> [CLI] bundle plan +Plan: 0 to add, 0 to change, 0 to delete, 2 unchanged + >>> [CLI] bundle destroy --auto-approve The following resources will be deleted: delete resources.postgres_branches.main diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/script b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/script index 0e7cbe6b7cb..77c51554a9d 100644 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/script +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/script @@ -25,3 +25,6 @@ trace cat databricks.yml trace $CLI bundle deploy --auto-approve trace $CLI postgres get-snapshot-schedule "${schedule_name}" | snapshot_schedule_fields print_requests.py --del-body parent,project_id,branch_id --sort --get '//postgres' '^//workspace-files/' '^//workspace/' '^//telemetry-ext' '^//operations/' > out.requests.remove.txt + +title "Plan again to confirm no drift after removal" +trace $CLI bundle plan From 120176f2a9bfd12ce5a786e5c3e51440dae7031d Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Tue, 1 Sep 2026 08:51:56 +0000 Subject: [PATCH 06/22] task generate-check --- bundle/direct/dresources/apitypes.generated.yml | 2 ++ bundle/direct/dresources/resources.generated.yml | 2 ++ bundle/internal/validation/generated/enum_fields.go | 2 ++ bundle/internal/validation/generated/required_fields.go | 5 +++++ 4 files changed, 11 insertions(+) diff --git a/bundle/direct/dresources/apitypes.generated.yml b/bundle/direct/dresources/apitypes.generated.yml index ec2e3c2519c..ebb50c43c49 100644 --- a/bundle/direct/dresources/apitypes.generated.yml +++ b/bundle/direct/dresources/apitypes.generated.yml @@ -46,6 +46,8 @@ postgres_projects: postgres.ProjectStatus postgres_roles: postgres.RoleRoleStatus +postgres_snapshot_schedules: postgres.UpdateBranchRequest + postgres_synced_tables: postgres.SyncedTableSyncedTableSpec quality_monitors: catalog.CreateMonitor diff --git a/bundle/direct/dresources/resources.generated.yml b/bundle/direct/dresources/resources.generated.yml index 264ba81eca1..85a0466d499 100644 --- a/bundle/direct/dresources/resources.generated.yml +++ b/bundle/direct/dresources/resources.generated.yml @@ -370,6 +370,8 @@ resources: - field: postgres_role reason: spec:input_only + # postgres_snapshot_schedules: no api field behaviors + postgres_synced_tables: ignore_remote_changes: diff --git a/bundle/internal/validation/generated/enum_fields.go b/bundle/internal/validation/generated/enum_fields.go index e65f7ea4348..cb3a8f085de 100644 --- a/bundle/internal/validation/generated/enum_fields.go +++ b/bundle/internal/validation/generated/enum_fields.go @@ -238,6 +238,8 @@ var EnumFields = map[string][]string{ "resources.postgres_roles.*.identity_type": {"GROUP", "SERVICE_PRINCIPAL", "USER"}, "resources.postgres_roles.*.membership_roles[*]": {"DATABRICKS_SUPERUSER"}, + "resources.postgres_snapshot_schedules.*.schedule[*].weekly_schedule.day_of_week": {"FRIDAY", "MONDAY", "SATURDAY", "SUNDAY", "THURSDAY", "TUESDAY", "WEDNESDAY"}, + "resources.postgres_synced_tables.*.extra_columns[*].maintenance": {"STORED_GENERATED"}, "resources.postgres_synced_tables.*.new_pipeline_spec.pipeline_channel": {"CURRENT", "PREVIEW"}, "resources.postgres_synced_tables.*.scheduling_policy": {"CONTINUOUS", "SNAPSHOT", "TRIGGERED"}, diff --git a/bundle/internal/validation/generated/required_fields.go b/bundle/internal/validation/generated/required_fields.go index fcdd9b11ab9..7a8a027a10d 100644 --- a/bundle/internal/validation/generated/required_fields.go +++ b/bundle/internal/validation/generated/required_fields.go @@ -269,6 +269,11 @@ var RequiredFields = map[string][]string{ "resources.postgres_roles.*": {"role_id", "parent"}, + "resources.postgres_snapshot_schedules.*": {"branch"}, + "resources.postgres_snapshot_schedules.*.schedule[*]": {"retention"}, + "resources.postgres_snapshot_schedules.*.schedule[*].monthly_schedule": {"day"}, + "resources.postgres_snapshot_schedules.*.schedule[*].weekly_schedule": {"day_of_week"}, + "resources.postgres_synced_tables.*": {"synced_table_id"}, "resources.postgres_synced_tables.*.extra_columns[*]": {"column_name", "column_type"}, "resources.postgres_synced_tables.*.type_overrides[*]": {"column_name", "pg_type"}, From 877b6ae5087fb52874b2d089b1895b997dc8e821 Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Tue, 8 Sep 2026 08:26:10 +0000 Subject: [PATCH 07/22] Wire postgres_snapshot_schedules into resource exhaustiveness checks Completes wiring for the postgres_snapshot_schedules resource so it satisfies the repo-wide "for all resources" guard tests: - Add MarshalJSON/UnmarshalJSON to resources.PostgresSnapshotSchedule so the outer wrapper's id/url/lifecycle/modified_status survive a JSON round-trip instead of being dropped by the embedded config marshaler (mirrors resources.PostgresBranch). - Pin the resource to Beta via launchStageOverrides and cover it in the launch-stage override test. - Populate PostgresSnapshotSchedules in the StateToBundle fixtures. - Mark it direct-engine only in the Terraform lifecycle test; the pinned provider has no resource that maps to a snapshot schedule. Regenerate the resource's out.test.toml snapshots to pick up the DMS EnvMatrix inherited from a parent test.toml. Co-authored-by: Isaac --- .../postgres_snapshot_schedule/out.test.toml | 1 + .../basic/out.test.toml | 1 + .../out-of-band/out.test.toml | 1 + .../resources/postgres_snapshot_schedule.go | 8 ++ bundle/deploy/terraform/lifecycle_test.go | 4 + bundle/internal/annotation/preview.go | 15 ++-- bundle/internal/schema/parser_test.go | 1 + bundle/statemgmt/state_load_test.go | 89 ++++++++++++------- 8 files changed, 79 insertions(+), 41 deletions(-) diff --git a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/out.test.toml b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/out.test.toml index 0938e678987..27ec2a7fcd6 100644 --- a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/out.test.toml +++ b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/out.test.toml @@ -1,2 +1,3 @@ Cloud = false EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] +EnvMatrix.DMS = [""] diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.test.toml b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.test.toml index 1314e661c24..7ad46517eca 100644 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.test.toml +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.test.toml @@ -2,3 +2,4 @@ Cloud = true CloudEnvs.azure = false CloudEnvs.gcp = false EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] +EnvMatrix.DMS = ["", "true"] diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/out.test.toml b/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/out.test.toml index 1314e661c24..7ad46517eca 100644 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/out.test.toml +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/out.test.toml @@ -2,3 +2,4 @@ Cloud = true CloudEnvs.azure = false CloudEnvs.gcp = false EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] +EnvMatrix.DMS = ["", "true"] diff --git a/bundle/config/resources/postgres_snapshot_schedule.go b/bundle/config/resources/postgres_snapshot_schedule.go index 374aa55f355..c03caa81ee4 100644 --- a/bundle/config/resources/postgres_snapshot_schedule.go +++ b/bundle/config/resources/postgres_snapshot_schedule.go @@ -40,6 +40,14 @@ type PostgresSnapshotSchedule struct { PostgresSnapshotScheduleConfig } +func (b *PostgresSnapshotSchedule) UnmarshalJSON(data []byte) error { + return marshal.Unmarshal(data, b) +} + +func (b PostgresSnapshotSchedule) MarshalJSON() ([]byte, error) { + return marshal.Marshal(b) +} + func (b *PostgresSnapshotSchedule) Exists(ctx context.Context, w *databricks.WorkspaceClient, name string) (bool, error) { _, err := w.Postgres.GetSnapshotSchedule(ctx, postgres.GetSnapshotScheduleRequest{Name: name}) if err != nil { diff --git a/bundle/deploy/terraform/lifecycle_test.go b/bundle/deploy/terraform/lifecycle_test.go index eaf3040f1c7..e0fd98664e5 100644 --- a/bundle/deploy/terraform/lifecycle_test.go +++ b/bundle/deploy/terraform/lifecycle_test.go @@ -21,6 +21,10 @@ func TestConvertLifecycleForAllResources(t *testing.T) { "genie_spaces", "instance_pools", "job_runs", + // The Terraform provider has no resource that maps to a snapshot schedule, + // so it is deployed through the direct engine only (see the resource's + // acceptance test.toml). + "postgres_snapshot_schedules", "secrets", "vector_search_endpoints", "vector_search_indexes", diff --git a/bundle/internal/annotation/preview.go b/bundle/internal/annotation/preview.go index 444a8585d18..b4be7348526 100644 --- a/bundle/internal/annotation/preview.go +++ b/bundle/internal/annotation/preview.go @@ -27,13 +27,14 @@ func PreviewTag(stage clijson.LaunchStage) string { // fully-qualified Go type paths (PkgPath + "." + Name), matching getPath in // bundle/internal/schema. var launchStageOverrides = map[string]clijson.LaunchStage{ - "github.com/databricks/cli/bundle/config/resources.PostgresBranch": clijson.LaunchStagePublicBeta, - "github.com/databricks/cli/bundle/config/resources.PostgresCatalog": clijson.LaunchStagePublicBeta, - "github.com/databricks/cli/bundle/config/resources.PostgresDatabase": clijson.LaunchStagePublicBeta, - "github.com/databricks/cli/bundle/config/resources.PostgresEndpoint": clijson.LaunchStagePublicBeta, - "github.com/databricks/cli/bundle/config/resources.PostgresProject": clijson.LaunchStagePublicBeta, - "github.com/databricks/cli/bundle/config/resources.PostgresRole": clijson.LaunchStagePublicBeta, - "github.com/databricks/cli/bundle/config/resources.PostgresSyncedTable": clijson.LaunchStagePublicBeta, + "github.com/databricks/cli/bundle/config/resources.PostgresBranch": clijson.LaunchStagePublicBeta, + "github.com/databricks/cli/bundle/config/resources.PostgresCatalog": clijson.LaunchStagePublicBeta, + "github.com/databricks/cli/bundle/config/resources.PostgresDatabase": clijson.LaunchStagePublicBeta, + "github.com/databricks/cli/bundle/config/resources.PostgresEndpoint": clijson.LaunchStagePublicBeta, + "github.com/databricks/cli/bundle/config/resources.PostgresProject": clijson.LaunchStagePublicBeta, + "github.com/databricks/cli/bundle/config/resources.PostgresRole": clijson.LaunchStagePublicBeta, + "github.com/databricks/cli/bundle/config/resources.PostgresSnapshotSchedule": clijson.LaunchStagePublicBeta, + "github.com/databricks/cli/bundle/config/resources.PostgresSyncedTable": clijson.LaunchStagePublicBeta, } // OverrideLaunchStage raises a field's launch stage to the type's configured diff --git a/bundle/internal/schema/parser_test.go b/bundle/internal/schema/parser_test.go index 9b88228d89d..7e7f9946b63 100644 --- a/bundle/internal/schema/parser_test.go +++ b/bundle/internal/schema/parser_test.go @@ -88,6 +88,7 @@ func TestPostgresResourcesHaveLaunchStageOverride(t *testing.T) { reflect.TypeFor[resources.PostgresEndpoint](), reflect.TypeFor[resources.PostgresProject](), reflect.TypeFor[resources.PostgresRole](), + reflect.TypeFor[resources.PostgresSnapshotSchedule](), reflect.TypeFor[resources.PostgresSyncedTable](), } diff --git a/bundle/statemgmt/state_load_test.go b/bundle/statemgmt/state_load_test.go index ab39a4917b0..52ea36079f3 100644 --- a/bundle/statemgmt/state_load_test.go +++ b/bundle/statemgmt/state_load_test.go @@ -26,40 +26,41 @@ func TestStateToBundleEmptyLocalResources(t *testing.T) { } state := ExportedResourcesMap{ - "resources.jobs.test_job": {ID: "1"}, - "resources.job_runs.test_job_run": {ID: "1"}, - "resources.pipelines.test_pipeline": {ID: "1"}, - "resources.models.test_mlflow_model": {ID: "1"}, - "resources.experiments.test_mlflow_experiment": {ID: "1"}, - "resources.model_serving_endpoints.test_model_serving": {ID: "1"}, - "resources.registered_models.test_registered_model": {ID: "1"}, - "resources.quality_monitors.test_monitor": {ID: "1"}, - "resources.catalogs.test_catalog": {ID: "1"}, - "resources.schemas.test_schema": {ID: "1"}, - "resources.external_locations.test_external_location": {ID: "1"}, - "resources.volumes.test_volume": {ID: "1"}, - "resources.clusters.test_cluster": {ID: "1"}, - "resources.dashboards.test_dashboard": {ID: "1"}, - "resources.genie_spaces.test_genie_space": {ID: "1"}, - "resources.apps.test_app": {ID: "app1"}, - "resources.secret_scopes.test_secret_scope": {ID: "secret_scope1"}, - "resources.sql_warehouses.test_sql_warehouse": {ID: "1"}, - "resources.database_instances.test_database_instance": {ID: "1"}, - "resources.database_catalogs.test_database_catalog": {ID: "1"}, - "resources.synced_database_tables.test_synced_database_table": {ID: "1"}, - "resources.alerts.test_alert": {ID: "1"}, - "resources.postgres_projects.test_postgres_project": {ID: "projects/test-project"}, - "resources.postgres_branches.test_postgres_branch": {ID: "projects/test-project/branches/main"}, - "resources.postgres_endpoints.test_postgres_endpoint": {ID: "projects/test-project/branches/main/endpoints/primary"}, - "resources.postgres_catalogs.test_postgres_catalog": {ID: "catalogs/test_catalog"}, - "resources.postgres_databases.test_postgres_database": {ID: "projects/test-project/branches/main/databases/test-db"}, - "resources.postgres_roles.test_postgres_role": {ID: "projects/test-project/branches/main/roles/test-role"}, - "resources.postgres_synced_tables.test_postgres_synced_table": {ID: "synced_tables/main.public.test_synced_table"}, - "resources.vector_search_endpoints.test_vector_search_endpoint": {ID: "vs-endpoint-1"}, - "resources.vector_search_indexes.test_vector_search_index": {ID: "vs-index-1"}, - "resources.instance_pools.test_instance_pool": {ID: "1"}, - "resources.secrets.test_secret": {ID: "main.default.test_secret"}, - "resources.cluster_policies.test_cluster_policy": {ID: "cp-1"}, + "resources.jobs.test_job": {ID: "1"}, + "resources.job_runs.test_job_run": {ID: "1"}, + "resources.pipelines.test_pipeline": {ID: "1"}, + "resources.models.test_mlflow_model": {ID: "1"}, + "resources.experiments.test_mlflow_experiment": {ID: "1"}, + "resources.model_serving_endpoints.test_model_serving": {ID: "1"}, + "resources.registered_models.test_registered_model": {ID: "1"}, + "resources.quality_monitors.test_monitor": {ID: "1"}, + "resources.catalogs.test_catalog": {ID: "1"}, + "resources.schemas.test_schema": {ID: "1"}, + "resources.external_locations.test_external_location": {ID: "1"}, + "resources.volumes.test_volume": {ID: "1"}, + "resources.clusters.test_cluster": {ID: "1"}, + "resources.dashboards.test_dashboard": {ID: "1"}, + "resources.genie_spaces.test_genie_space": {ID: "1"}, + "resources.apps.test_app": {ID: "app1"}, + "resources.secret_scopes.test_secret_scope": {ID: "secret_scope1"}, + "resources.sql_warehouses.test_sql_warehouse": {ID: "1"}, + "resources.database_instances.test_database_instance": {ID: "1"}, + "resources.database_catalogs.test_database_catalog": {ID: "1"}, + "resources.synced_database_tables.test_synced_database_table": {ID: "1"}, + "resources.alerts.test_alert": {ID: "1"}, + "resources.postgres_projects.test_postgres_project": {ID: "projects/test-project"}, + "resources.postgres_branches.test_postgres_branch": {ID: "projects/test-project/branches/main"}, + "resources.postgres_endpoints.test_postgres_endpoint": {ID: "projects/test-project/branches/main/endpoints/primary"}, + "resources.postgres_catalogs.test_postgres_catalog": {ID: "catalogs/test_catalog"}, + "resources.postgres_databases.test_postgres_database": {ID: "projects/test-project/branches/main/databases/test-db"}, + "resources.postgres_roles.test_postgres_role": {ID: "projects/test-project/branches/main/roles/test-role"}, + "resources.postgres_synced_tables.test_postgres_synced_table": {ID: "synced_tables/main.public.test_synced_table"}, + "resources.postgres_snapshot_schedules.test_postgres_snapshot_schedule": {ID: "projects/test-project/branches/main/snapshot-schedule"}, + "resources.vector_search_endpoints.test_vector_search_endpoint": {ID: "vs-endpoint-1"}, + "resources.vector_search_indexes.test_vector_search_index": {ID: "vs-index-1"}, + "resources.instance_pools.test_instance_pool": {ID: "1"}, + "resources.secrets.test_secret": {ID: "main.default.test_secret"}, + "resources.cluster_policies.test_cluster_policy": {ID: "cp-1"}, } err := StateToBundle(t.Context(), state, &config) assert.NoError(t, err) @@ -146,6 +147,9 @@ func TestStateToBundleEmptyLocalResources(t *testing.T) { assert.Equal(t, "synced_tables/main.public.test_synced_table", config.Resources.PostgresSyncedTables["test_postgres_synced_table"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.PostgresSyncedTables["test_postgres_synced_table"].ModifiedStatus) + assert.Equal(t, "projects/test-project/branches/main/snapshot-schedule", config.Resources.PostgresSnapshotSchedules["test_postgres_snapshot_schedule"].ID) + assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.PostgresSnapshotSchedules["test_postgres_snapshot_schedule"].ModifiedStatus) + assert.Equal(t, "vs-endpoint-1", config.Resources.VectorSearchEndpoints["test_vector_search_endpoint"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.VectorSearchEndpoints["test_vector_search_endpoint"].ModifiedStatus) @@ -385,6 +389,13 @@ func TestStateToBundleEmptyRemoteResources(t *testing.T) { }, }, }, + PostgresSnapshotSchedules: map[string]*resources.PostgresSnapshotSchedule{ + "test_postgres_snapshot_schedule": { + PostgresSnapshotScheduleConfig: resources.PostgresSnapshotScheduleConfig{ + Branch: "projects/test-project/branches/main", + }, + }, + }, VectorSearchEndpoints: map[string]*resources.VectorSearchEndpoint{ "test_vector_search_endpoint": { CreateEndpoint: vectorsearch.CreateEndpoint{ @@ -509,6 +520,9 @@ func TestStateToBundleEmptyRemoteResources(t *testing.T) { assert.Empty(t, config.Resources.PostgresSyncedTables["test_postgres_synced_table"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.PostgresSyncedTables["test_postgres_synced_table"].ModifiedStatus) + assert.Empty(t, config.Resources.PostgresSnapshotSchedules["test_postgres_snapshot_schedule"].ID) + assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.PostgresSnapshotSchedules["test_postgres_snapshot_schedule"].ModifiedStatus) + assert.Empty(t, config.Resources.VectorSearchEndpoints["test_vector_search_endpoint"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.VectorSearchEndpoints["test_vector_search_endpoint"].ModifiedStatus) @@ -892,6 +906,13 @@ func TestStateToBundleModifiedResources(t *testing.T) { }, }, }, + PostgresSnapshotSchedules: map[string]*resources.PostgresSnapshotSchedule{ + "test_postgres_snapshot_schedule": { + PostgresSnapshotScheduleConfig: resources.PostgresSnapshotScheduleConfig{ + Branch: "projects/test-project/branches/main", + }, + }, + }, VectorSearchEndpoints: map[string]*resources.VectorSearchEndpoint{ "test_vector_search_endpoint": { CreateEndpoint: vectorsearch.CreateEndpoint{ From c032faa24bf8ad19065bdc2fe8f4efcc541a5517 Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Tue, 8 Sep 2026 08:45:18 +0000 Subject: [PATCH 08/22] Fix changelog fragment format for postgres_snapshot_schedules Add the required bullet marker and trailing PR link so the fragment passes check-changelog. Co-authored-by: Isaac --- .nextchanges/bundles/postgres-snapshot-schedules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nextchanges/bundles/postgres-snapshot-schedules.md b/.nextchanges/bundles/postgres-snapshot-schedules.md index b54efd7611f..5966edba1ad 100644 --- a/.nextchanges/bundles/postgres-snapshot-schedules.md +++ b/.nextchanges/bundles/postgres-snapshot-schedules.md @@ -1 +1 @@ -Add the `postgres_snapshot_schedules` bundle resource for managing a Lakebase Postgres branch's automatic-snapshot schedule (direct deployment engine only). +* Add the `postgres_snapshot_schedules` bundle resource for managing a Lakebase Postgres branch's automatic-snapshot schedule (direct deployment engine only). ([#6449](https://github.com/databricks/cli/pull/6449)) From 2aadf8633bb4b221893a828f0b976e82f65debec Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Tue, 8 Sep 2026 10:33:05 +0000 Subject: [PATCH 09/22] Resolve postgres_snapshot_schedules URL to the branch restore page The snapshot schedule has no web UI page of its own. Per agreement with the Postgres team, point its URL at the parent branch's restore view: lakebase/projects/{project_id}/branches/{branch_id}/restore, resolved from the resource's branch. Covered in TestInitializeURLs and reflected in the bind acceptance golden. Co-authored-by: Isaac --- .../bind/postgres_snapshot_schedule/output.txt | 4 ++-- bundle/config/mutator/initialize_urls_test.go | 9 +++++++++ .../resources/postgres_snapshot_schedule.go | 15 +++++++++++---- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt index 71102ecfd2c..daaeb7dce03 100644 --- a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt +++ b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt @@ -13,7 +13,7 @@ Resources: Postgres snapshot schedules: schedule1: Name: - URL: (not deployed) + URL: [DATABRICKS_URL]/lakebase/projects/test-project/branches/main/restore?w=[NUMID] >>> [CLI] bundle deployment unbind schedule1 @@ -27,4 +27,4 @@ Resources: Postgres snapshot schedules: schedule1: Name: - URL: (not deployed) + URL: [DATABRICKS_URL]/lakebase/projects/test-project/branches/main/restore?w=[NUMID] diff --git a/bundle/config/mutator/initialize_urls_test.go b/bundle/config/mutator/initialize_urls_test.go index b3e10660b31..c7b066ea1bb 100644 --- a/bundle/config/mutator/initialize_urls_test.go +++ b/bundle/config/mutator/initialize_urls_test.go @@ -101,6 +101,14 @@ func TestInitializeURLs(t *testing.T) { }, }, }, + PostgresSnapshotSchedules: map[string]*resources.PostgresSnapshotSchedule{ + "snapshotschedule1": { + BaseResource: resources.BaseResource{ID: "projects/myproject/branches/main/snapshot-schedule"}, + PostgresSnapshotScheduleConfig: resources.PostgresSnapshotScheduleConfig{ + Branch: "projects/myproject/branches/main", + }, + }, + }, }, }, } @@ -117,6 +125,7 @@ func TestInitializeURLs(t *testing.T) { "schema1": "https://mycompany.databricks.com/explore/data/catalog/schema?w=123456", "cluster1": "https://mycompany.databricks.com/compute/clusters/1017-103929-vlr7jzcf?w=123456", "dashboard1": "https://mycompany.databricks.com/dashboardsv3/01ef8d56871e1d50ae30ce7375e42478/published?w=123456", + "snapshotschedule1": "https://mycompany.databricks.com/lakebase/projects/myproject/branches/main/restore?w=123456", } err := initializeForWorkspace(b, "123456", "https://mycompany.databricks.com/") diff --git a/bundle/config/resources/postgres_snapshot_schedule.go b/bundle/config/resources/postgres_snapshot_schedule.go index c03caa81ee4..9497eb3d682 100644 --- a/bundle/config/resources/postgres_snapshot_schedule.go +++ b/bundle/config/resources/postgres_snapshot_schedule.go @@ -3,6 +3,7 @@ package resources import ( "context" "net/url" + "strings" "github.com/databricks/cli/libs/log" "github.com/databricks/databricks-sdk-go" @@ -72,10 +73,16 @@ func (b *PostgresSnapshotSchedule) GetName() string { } func (b *PostgresSnapshotSchedule) GetURL() string { - // The IDs in the API do not (yet) map to IDs in the web UI. - return "" + return b.URL } -func (b *PostgresSnapshotSchedule) InitializeURL(_ url.URL) { - // The IDs in the API do not (yet) map to IDs in the web UI. +// InitializeURL points at the branch's restore page. The snapshot schedule has +// no page of its own; the Postgres team confirmed snapshots surface under the +// branch's restore view. Branch is "projects/{project_id}/branches/{branch_id}". +func (b *PostgresSnapshotSchedule) InitializeURL(baseURL url.URL) { + if b.Branch == "" { + return + } + baseURL.Path = "lakebase/" + strings.TrimRight(b.Branch, "/") + "/restore" + b.URL = baseURL.String() } From 6a4da27725ed5dc553ca38417b9eba0ddad9c05b Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Tue, 8 Sep 2026 10:40:00 +0000 Subject: [PATCH 10/22] Build snapshot schedule URL via workspaceurls helper Register a postgres_snapshot_schedules pattern (lakebase/%s/restore, %s = parent branch) and use workspaceurls.ResourceURL in InitializeURL instead of hand-assembling the path, matching every other resource. Co-authored-by: Isaac --- .../resources/postgres_snapshot_schedule.go | 5 ++-- libs/workspaceurls/urls.go | 28 +++++++++++-------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/bundle/config/resources/postgres_snapshot_schedule.go b/bundle/config/resources/postgres_snapshot_schedule.go index 9497eb3d682..232f09099d2 100644 --- a/bundle/config/resources/postgres_snapshot_schedule.go +++ b/bundle/config/resources/postgres_snapshot_schedule.go @@ -3,9 +3,9 @@ package resources import ( "context" "net/url" - "strings" "github.com/databricks/cli/libs/log" + "github.com/databricks/cli/libs/workspaceurls" "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/marshal" "github.com/databricks/databricks-sdk-go/service/postgres" @@ -83,6 +83,5 @@ func (b *PostgresSnapshotSchedule) InitializeURL(baseURL url.URL) { if b.Branch == "" { return } - baseURL.Path = "lakebase/" + strings.TrimRight(b.Branch, "/") + "/restore" - b.URL = baseURL.String() + b.URL = workspaceurls.ResourceURL(baseURL, "postgres_snapshot_schedules", b.Branch) } diff --git a/libs/workspaceurls/urls.go b/libs/workspaceurls/urls.go index 61c3f271468..16e0fd39eff 100644 --- a/libs/workspaceurls/urls.go +++ b/libs/workspaceurls/urls.go @@ -24,18 +24,22 @@ var resourceURLPatterns = map[string]string{ "notebooks": "#notebook/%s", "pipelines": "pipelines/%s", "postgres_catalogs": "explore/data/%s", - "postgres_synced_tables": "explore/data/%s", - "quality_monitors": "explore/data/%s", - "queries": "sql/editor/%s", - "registered_models": "explore/data/models/%s", - "schemas": "explore/data/%s", - "secrets": "explore/data/%s", - "synced_database_tables": "explore/data/%s", - "vector_search_endpoints": "compute/vector-search/%s", - "vector_search_indexes": "explore/data/%s", - "volumes": "explore/data/volumes/%s", - "warehouses": "sql/warehouses/%s", - "instance_pools": "compute/instance-pools/%s", + // The snapshot schedule has no page of its own; %s is the parent branch + // ("projects/{project_id}/branches/{branch_id}"), whose restore view is + // where snapshots surface. + "postgres_snapshot_schedules": "lakebase/%s/restore", + "postgres_synced_tables": "explore/data/%s", + "quality_monitors": "explore/data/%s", + "queries": "sql/editor/%s", + "registered_models": "explore/data/models/%s", + "schemas": "explore/data/%s", + "secrets": "explore/data/%s", + "synced_database_tables": "explore/data/%s", + "vector_search_endpoints": "compute/vector-search/%s", + "vector_search_indexes": "explore/data/%s", + "volumes": "explore/data/volumes/%s", + "warehouses": "sql/warehouses/%s", + "instance_pools": "compute/instance-pools/%s", } // resourceAliases lets callers use bundle-config plural names as synonyms for From 7b40ce754297e0a3c8806f672a6b164775b71155 Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Tue, 8 Sep 2026 11:19:18 +0000 Subject: [PATCH 11/22] Fix resource-type list tests and derive snapshot URL from ID Adding postgres_snapshot_schedules to workspaceurls broke tests that assert the exact ResourceTypes() list (cmd/experimental open command and its acceptance golden); update them. Also derive the branch from the schedule's resolved ID rather than the Branch field, which may hold an unresolved "${...}" reference at summary time. This matches the other parent-referencing postgres resources and correctly shows "(not deployed)" until the schedule has an ID. Co-authored-by: Isaac --- .../bind/postgres_snapshot_schedule/output.txt | 2 +- acceptance/experimental/open/output.txt | 3 ++- bundle/config/mutator/initialize_urls_test.go | 3 --- .../config/resources/postgres_snapshot_schedule.go | 13 ++++++++----- cmd/experimental/workspace_open_test.go | 5 +++-- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt index daaeb7dce03..96bae24cac4 100644 --- a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt +++ b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt @@ -27,4 +27,4 @@ Resources: Postgres snapshot schedules: schedule1: Name: - URL: [DATABRICKS_URL]/lakebase/projects/test-project/branches/main/restore?w=[NUMID] + URL: (not deployed) diff --git a/acceptance/experimental/open/output.txt b/acceptance/experimental/open/output.txt index 75591ed7423..c39e1700ae0 100644 --- a/acceptance/experimental/open/output.txt +++ b/acceptance/experimental/open/output.txt @@ -9,7 +9,7 @@ === unknown resource type >>> [CLI] experimental open --url unknown 123 -Error: unknown resource type "unknown", must be one of: alerts, apps, catalogs, cluster_policies, clusters, dashboards, database_catalogs, database_instances, experiments, genie_spaces, instance_pools, jobs, model_serving_endpoints, models, notebooks, pipelines, postgres_catalogs, postgres_synced_tables, quality_monitors, queries, registered_models, schemas, secrets, synced_database_tables, vector_search_endpoints, vector_search_indexes, volumes, warehouses +Error: unknown resource type "unknown", must be one of: alerts, apps, catalogs, cluster_policies, clusters, dashboards, database_catalogs, database_instances, experiments, genie_spaces, instance_pools, jobs, model_serving_endpoints, models, notebooks, pipelines, postgres_catalogs, postgres_snapshot_schedules, postgres_synced_tables, quality_monitors, queries, registered_models, schemas, secrets, synced_database_tables, vector_search_endpoints, vector_search_indexes, volumes, warehouses === test auto-completion handler >>> [CLI] __complete experimental open , @@ -30,6 +30,7 @@ models notebooks pipelines postgres_catalogs +postgres_snapshot_schedules postgres_synced_tables quality_monitors queries diff --git a/bundle/config/mutator/initialize_urls_test.go b/bundle/config/mutator/initialize_urls_test.go index c7b066ea1bb..fa736297fef 100644 --- a/bundle/config/mutator/initialize_urls_test.go +++ b/bundle/config/mutator/initialize_urls_test.go @@ -104,9 +104,6 @@ func TestInitializeURLs(t *testing.T) { PostgresSnapshotSchedules: map[string]*resources.PostgresSnapshotSchedule{ "snapshotschedule1": { BaseResource: resources.BaseResource{ID: "projects/myproject/branches/main/snapshot-schedule"}, - PostgresSnapshotScheduleConfig: resources.PostgresSnapshotScheduleConfig{ - Branch: "projects/myproject/branches/main", - }, }, }, }, diff --git a/bundle/config/resources/postgres_snapshot_schedule.go b/bundle/config/resources/postgres_snapshot_schedule.go index 232f09099d2..8e8ca5973ea 100644 --- a/bundle/config/resources/postgres_snapshot_schedule.go +++ b/bundle/config/resources/postgres_snapshot_schedule.go @@ -3,6 +3,7 @@ package resources import ( "context" "net/url" + "strings" "github.com/databricks/cli/libs/log" "github.com/databricks/cli/libs/workspaceurls" @@ -76,12 +77,14 @@ func (b *PostgresSnapshotSchedule) GetURL() string { return b.URL } -// InitializeURL points at the branch's restore page. The snapshot schedule has -// no page of its own; the Postgres team confirmed snapshots surface under the -// branch's restore view. Branch is "projects/{project_id}/branches/{branch_id}". +// InitializeURL points at the branch's restore page, where snapshots surface; +// the schedule has no page of its own. The branch is derived from this +// schedule's resolved ID ("projects/{project_id}/branches/{branch_id}/snapshot-schedule") +// rather than from Branch, which may still hold an unresolved "${...}" reference. func (b *PostgresSnapshotSchedule) InitializeURL(baseURL url.URL) { - if b.Branch == "" { + branch, _, ok := strings.Cut(b.ID, "/snapshot-schedule") + if !ok { return } - b.URL = workspaceurls.ResourceURL(baseURL, "postgres_snapshot_schedules", b.Branch) + b.URL = workspaceurls.ResourceURL(baseURL, "postgres_snapshot_schedules", branch) } diff --git a/cmd/experimental/workspace_open_test.go b/cmd/experimental/workspace_open_test.go index 95502694472..31bbc6657e7 100644 --- a/cmd/experimental/workspace_open_test.go +++ b/cmd/experimental/workspace_open_test.go @@ -67,7 +67,7 @@ func TestBuildWorkspaceURLFragmentBasedResources(t *testing.T) { func TestBuildWorkspaceURLUnknownResourceType(t *testing.T) { _, err := workspaceurls.BuildResourceURL("https://myworkspace.databricks.com", "unknown", "123", "") assert.ErrorContains(t, err, "unknown resource type \"unknown\"") - assert.ErrorContains(t, err, "alerts, apps, catalogs, cluster_policies, clusters, dashboards, database_catalogs, database_instances, experiments, genie_spaces, instance_pools, jobs, model_serving_endpoints, models, notebooks, pipelines, postgres_catalogs, postgres_synced_tables, quality_monitors, queries, registered_models, schemas, secrets, synced_database_tables, vector_search_endpoints, vector_search_indexes, volumes, warehouses") + assert.ErrorContains(t, err, "alerts, apps, catalogs, cluster_policies, clusters, dashboards, database_catalogs, database_instances, experiments, genie_spaces, instance_pools, jobs, model_serving_endpoints, models, notebooks, pipelines, postgres_catalogs, postgres_snapshot_schedules, postgres_synced_tables, quality_monitors, queries, registered_models, schemas, secrets, synced_database_tables, vector_search_endpoints, vector_search_indexes, volumes, warehouses") } func TestBuildWorkspaceURLHostWithTrailingSlash(t *testing.T) { @@ -124,6 +124,7 @@ func TestWorkspaceOpenCommandCompletion(t *testing.T) { "notebooks", "pipelines", "postgres_catalogs", + "postgres_snapshot_schedules", "postgres_synced_tables", "quality_monitors", "queries", @@ -149,7 +150,7 @@ func TestWorkspaceOpenCommandCompletionSecondArg(t *testing.T) { func TestWorkspaceOpenCommandHelpText(t *testing.T) { cmd := newWorkspaceOpenCommand() - assert.Contains(t, cmd.Long, "Supported resource types: alerts, apps, catalogs, cluster_policies, clusters, dashboards, database_catalogs, database_instances, experiments, genie_spaces, instance_pools, jobs, model_serving_endpoints, models, notebooks, pipelines, postgres_catalogs, postgres_synced_tables, quality_monitors, queries, registered_models, schemas, secrets, synced_database_tables, vector_search_endpoints, vector_search_indexes, volumes, warehouses.") + assert.Contains(t, cmd.Long, "Supported resource types: alerts, apps, catalogs, cluster_policies, clusters, dashboards, database_catalogs, database_instances, experiments, genie_spaces, instance_pools, jobs, model_serving_endpoints, models, notebooks, pipelines, postgres_catalogs, postgres_snapshot_schedules, postgres_synced_tables, quality_monitors, queries, registered_models, schemas, secrets, synced_database_tables, vector_search_endpoints, vector_search_indexes, volumes, warehouses.") assert.Contains(t, cmd.Long, "databricks experimental open jobs 123456789") assert.Contains(t, cmd.Long, "databricks experimental open notebooks /Users/user@example.com/my-notebook") assert.Contains(t, cmd.Long, "databricks experimental open registered_models catalog.schema.my_model") From adc3126c3dfc248086d51d3abe986469d0726a3a Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Tue, 8 Sep 2026 11:31:58 +0000 Subject: [PATCH 12/22] Remove postgres_snapshot_schedules from the noURL allowlist It now has a workspace URL, so TestBundleResourcePluralNamesResolveInWorkspaceURLs requires it to resolve rather than be empty. Co-authored-by: Isaac --- bundle/config/resources_test.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/bundle/config/resources_test.go b/bundle/config/resources_test.go index dfef773ff88..af4e9de53f4 100644 --- a/bundle/config/resources_test.go +++ b/bundle/config/resources_test.go @@ -128,14 +128,13 @@ func TestBundleResourcePluralNamesResolveInWorkspaceURLs(t *testing.T) { // A job run does have a workspace URL, but it's addressed by two IDs // (job + run) so it can't be expressed as a single-ID pattern here; it's // built in JobRun.InitializeURL via workspaceurls.JobRunURL instead. - "job_runs": true, - "postgres_branches": true, - "postgres_databases": true, - "postgres_endpoints": true, - "postgres_projects": true, - "postgres_roles": true, - "postgres_snapshot_schedules": true, - "secret_scopes": true, + "job_runs": true, + "postgres_branches": true, + "postgres_databases": true, + "postgres_endpoints": true, + "postgres_projects": true, + "postgres_roles": true, + "secret_scopes": true, } supported := SupportedResources() From 21c12ccb3ff70cb547855d0f03ce5f38267380ea Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Tue, 8 Sep 2026 11:59:31 +0000 Subject: [PATCH 13/22] Give PostgresSnapshotScheduleConfig a value-receiver MarshalJSON Main's new TestMarshalerValueReceiver requires marshalling by value and by pointer to agree; match the sibling postgres configs. Co-authored-by: Isaac --- bundle/config/resources/postgres_snapshot_schedule.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundle/config/resources/postgres_snapshot_schedule.go b/bundle/config/resources/postgres_snapshot_schedule.go index 8e8ca5973ea..8c162430498 100644 --- a/bundle/config/resources/postgres_snapshot_schedule.go +++ b/bundle/config/resources/postgres_snapshot_schedule.go @@ -33,7 +33,7 @@ func (c *PostgresSnapshotScheduleConfig) UnmarshalJSON(b []byte) error { return marshal.Unmarshal(b, c) } -func (c *PostgresSnapshotScheduleConfig) MarshalJSON() ([]byte, error) { +func (c PostgresSnapshotScheduleConfig) MarshalJSON() ([]byte, error) { return marshal.Marshal(c) } From 77ae3b506e670d2b0b8d80ad95a4285c8fe6e02d Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Tue, 8 Sep 2026 12:37:42 +0000 Subject: [PATCH 14/22] Remove URL handling from postgres_snapshot_schedules The Lakebase web UI addresses resources by uid, not by the resource name in bundle state, so the name-based URL was wrong. Revert to no URL (back in the noURL allowlist) until a uid-based scheme is designed. Co-authored-by: Isaac --- .../postgres_snapshot_schedule/output.txt | 2 +- acceptance/experimental/open/output.txt | 3 +- bundle/config/mutator/initialize_urls_test.go | 6 ---- .../resources/postgres_snapshot_schedule.go | 17 +++-------- bundle/config/resources_test.go | 15 +++++----- cmd/experimental/workspace_open_test.go | 5 ++-- libs/workspaceurls/urls.go | 28 ++++++++----------- 7 files changed, 28 insertions(+), 48 deletions(-) diff --git a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt index 96bae24cac4..71102ecfd2c 100644 --- a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt +++ b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt @@ -13,7 +13,7 @@ Resources: Postgres snapshot schedules: schedule1: Name: - URL: [DATABRICKS_URL]/lakebase/projects/test-project/branches/main/restore?w=[NUMID] + URL: (not deployed) >>> [CLI] bundle deployment unbind schedule1 diff --git a/acceptance/experimental/open/output.txt b/acceptance/experimental/open/output.txt index c39e1700ae0..75591ed7423 100644 --- a/acceptance/experimental/open/output.txt +++ b/acceptance/experimental/open/output.txt @@ -9,7 +9,7 @@ === unknown resource type >>> [CLI] experimental open --url unknown 123 -Error: unknown resource type "unknown", must be one of: alerts, apps, catalogs, cluster_policies, clusters, dashboards, database_catalogs, database_instances, experiments, genie_spaces, instance_pools, jobs, model_serving_endpoints, models, notebooks, pipelines, postgres_catalogs, postgres_snapshot_schedules, postgres_synced_tables, quality_monitors, queries, registered_models, schemas, secrets, synced_database_tables, vector_search_endpoints, vector_search_indexes, volumes, warehouses +Error: unknown resource type "unknown", must be one of: alerts, apps, catalogs, cluster_policies, clusters, dashboards, database_catalogs, database_instances, experiments, genie_spaces, instance_pools, jobs, model_serving_endpoints, models, notebooks, pipelines, postgres_catalogs, postgres_synced_tables, quality_monitors, queries, registered_models, schemas, secrets, synced_database_tables, vector_search_endpoints, vector_search_indexes, volumes, warehouses === test auto-completion handler >>> [CLI] __complete experimental open , @@ -30,7 +30,6 @@ models notebooks pipelines postgres_catalogs -postgres_snapshot_schedules postgres_synced_tables quality_monitors queries diff --git a/bundle/config/mutator/initialize_urls_test.go b/bundle/config/mutator/initialize_urls_test.go index fa736297fef..b3e10660b31 100644 --- a/bundle/config/mutator/initialize_urls_test.go +++ b/bundle/config/mutator/initialize_urls_test.go @@ -101,11 +101,6 @@ func TestInitializeURLs(t *testing.T) { }, }, }, - PostgresSnapshotSchedules: map[string]*resources.PostgresSnapshotSchedule{ - "snapshotschedule1": { - BaseResource: resources.BaseResource{ID: "projects/myproject/branches/main/snapshot-schedule"}, - }, - }, }, }, } @@ -122,7 +117,6 @@ func TestInitializeURLs(t *testing.T) { "schema1": "https://mycompany.databricks.com/explore/data/catalog/schema?w=123456", "cluster1": "https://mycompany.databricks.com/compute/clusters/1017-103929-vlr7jzcf?w=123456", "dashboard1": "https://mycompany.databricks.com/dashboardsv3/01ef8d56871e1d50ae30ce7375e42478/published?w=123456", - "snapshotschedule1": "https://mycompany.databricks.com/lakebase/projects/myproject/branches/main/restore?w=123456", } err := initializeForWorkspace(b, "123456", "https://mycompany.databricks.com/") diff --git a/bundle/config/resources/postgres_snapshot_schedule.go b/bundle/config/resources/postgres_snapshot_schedule.go index 8c162430498..6c0d353429f 100644 --- a/bundle/config/resources/postgres_snapshot_schedule.go +++ b/bundle/config/resources/postgres_snapshot_schedule.go @@ -3,10 +3,8 @@ package resources import ( "context" "net/url" - "strings" "github.com/databricks/cli/libs/log" - "github.com/databricks/cli/libs/workspaceurls" "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/marshal" "github.com/databricks/databricks-sdk-go/service/postgres" @@ -74,17 +72,10 @@ func (b *PostgresSnapshotSchedule) GetName() string { } func (b *PostgresSnapshotSchedule) GetURL() string { - return b.URL + // The IDs in the API do not (yet) map to IDs in the web UI. + return "" } -// InitializeURL points at the branch's restore page, where snapshots surface; -// the schedule has no page of its own. The branch is derived from this -// schedule's resolved ID ("projects/{project_id}/branches/{branch_id}/snapshot-schedule") -// rather than from Branch, which may still hold an unresolved "${...}" reference. -func (b *PostgresSnapshotSchedule) InitializeURL(baseURL url.URL) { - branch, _, ok := strings.Cut(b.ID, "/snapshot-schedule") - if !ok { - return - } - b.URL = workspaceurls.ResourceURL(baseURL, "postgres_snapshot_schedules", branch) +func (b *PostgresSnapshotSchedule) InitializeURL(_ url.URL) { + // The IDs in the API do not (yet) map to IDs in the web UI. } diff --git a/bundle/config/resources_test.go b/bundle/config/resources_test.go index af4e9de53f4..dfef773ff88 100644 --- a/bundle/config/resources_test.go +++ b/bundle/config/resources_test.go @@ -128,13 +128,14 @@ func TestBundleResourcePluralNamesResolveInWorkspaceURLs(t *testing.T) { // A job run does have a workspace URL, but it's addressed by two IDs // (job + run) so it can't be expressed as a single-ID pattern here; it's // built in JobRun.InitializeURL via workspaceurls.JobRunURL instead. - "job_runs": true, - "postgres_branches": true, - "postgres_databases": true, - "postgres_endpoints": true, - "postgres_projects": true, - "postgres_roles": true, - "secret_scopes": true, + "job_runs": true, + "postgres_branches": true, + "postgres_databases": true, + "postgres_endpoints": true, + "postgres_projects": true, + "postgres_roles": true, + "postgres_snapshot_schedules": true, + "secret_scopes": true, } supported := SupportedResources() diff --git a/cmd/experimental/workspace_open_test.go b/cmd/experimental/workspace_open_test.go index 31bbc6657e7..95502694472 100644 --- a/cmd/experimental/workspace_open_test.go +++ b/cmd/experimental/workspace_open_test.go @@ -67,7 +67,7 @@ func TestBuildWorkspaceURLFragmentBasedResources(t *testing.T) { func TestBuildWorkspaceURLUnknownResourceType(t *testing.T) { _, err := workspaceurls.BuildResourceURL("https://myworkspace.databricks.com", "unknown", "123", "") assert.ErrorContains(t, err, "unknown resource type \"unknown\"") - assert.ErrorContains(t, err, "alerts, apps, catalogs, cluster_policies, clusters, dashboards, database_catalogs, database_instances, experiments, genie_spaces, instance_pools, jobs, model_serving_endpoints, models, notebooks, pipelines, postgres_catalogs, postgres_snapshot_schedules, postgres_synced_tables, quality_monitors, queries, registered_models, schemas, secrets, synced_database_tables, vector_search_endpoints, vector_search_indexes, volumes, warehouses") + assert.ErrorContains(t, err, "alerts, apps, catalogs, cluster_policies, clusters, dashboards, database_catalogs, database_instances, experiments, genie_spaces, instance_pools, jobs, model_serving_endpoints, models, notebooks, pipelines, postgres_catalogs, postgres_synced_tables, quality_monitors, queries, registered_models, schemas, secrets, synced_database_tables, vector_search_endpoints, vector_search_indexes, volumes, warehouses") } func TestBuildWorkspaceURLHostWithTrailingSlash(t *testing.T) { @@ -124,7 +124,6 @@ func TestWorkspaceOpenCommandCompletion(t *testing.T) { "notebooks", "pipelines", "postgres_catalogs", - "postgres_snapshot_schedules", "postgres_synced_tables", "quality_monitors", "queries", @@ -150,7 +149,7 @@ func TestWorkspaceOpenCommandCompletionSecondArg(t *testing.T) { func TestWorkspaceOpenCommandHelpText(t *testing.T) { cmd := newWorkspaceOpenCommand() - assert.Contains(t, cmd.Long, "Supported resource types: alerts, apps, catalogs, cluster_policies, clusters, dashboards, database_catalogs, database_instances, experiments, genie_spaces, instance_pools, jobs, model_serving_endpoints, models, notebooks, pipelines, postgres_catalogs, postgres_snapshot_schedules, postgres_synced_tables, quality_monitors, queries, registered_models, schemas, secrets, synced_database_tables, vector_search_endpoints, vector_search_indexes, volumes, warehouses.") + assert.Contains(t, cmd.Long, "Supported resource types: alerts, apps, catalogs, cluster_policies, clusters, dashboards, database_catalogs, database_instances, experiments, genie_spaces, instance_pools, jobs, model_serving_endpoints, models, notebooks, pipelines, postgres_catalogs, postgres_synced_tables, quality_monitors, queries, registered_models, schemas, secrets, synced_database_tables, vector_search_endpoints, vector_search_indexes, volumes, warehouses.") assert.Contains(t, cmd.Long, "databricks experimental open jobs 123456789") assert.Contains(t, cmd.Long, "databricks experimental open notebooks /Users/user@example.com/my-notebook") assert.Contains(t, cmd.Long, "databricks experimental open registered_models catalog.schema.my_model") diff --git a/libs/workspaceurls/urls.go b/libs/workspaceurls/urls.go index 16e0fd39eff..61c3f271468 100644 --- a/libs/workspaceurls/urls.go +++ b/libs/workspaceurls/urls.go @@ -24,22 +24,18 @@ var resourceURLPatterns = map[string]string{ "notebooks": "#notebook/%s", "pipelines": "pipelines/%s", "postgres_catalogs": "explore/data/%s", - // The snapshot schedule has no page of its own; %s is the parent branch - // ("projects/{project_id}/branches/{branch_id}"), whose restore view is - // where snapshots surface. - "postgres_snapshot_schedules": "lakebase/%s/restore", - "postgres_synced_tables": "explore/data/%s", - "quality_monitors": "explore/data/%s", - "queries": "sql/editor/%s", - "registered_models": "explore/data/models/%s", - "schemas": "explore/data/%s", - "secrets": "explore/data/%s", - "synced_database_tables": "explore/data/%s", - "vector_search_endpoints": "compute/vector-search/%s", - "vector_search_indexes": "explore/data/%s", - "volumes": "explore/data/volumes/%s", - "warehouses": "sql/warehouses/%s", - "instance_pools": "compute/instance-pools/%s", + "postgres_synced_tables": "explore/data/%s", + "quality_monitors": "explore/data/%s", + "queries": "sql/editor/%s", + "registered_models": "explore/data/models/%s", + "schemas": "explore/data/%s", + "secrets": "explore/data/%s", + "synced_database_tables": "explore/data/%s", + "vector_search_endpoints": "compute/vector-search/%s", + "vector_search_indexes": "explore/data/%s", + "volumes": "explore/data/volumes/%s", + "warehouses": "sql/warehouses/%s", + "instance_pools": "compute/instance-pools/%s", } // resourceAliases lets callers use bundle-config plural names as synonyms for From 0ae783f1fd7b401feefbb29a866dc5cb740d1200 Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Tue, 8 Sep 2026 12:37:52 +0000 Subject: [PATCH 15/22] Only allow snapshot schedules on the root branch The backend rejects a snapshot schedule on any non-root branch ("not allowed to snapshot non-root branch"), which surfaced only on cloud. Teach the testserver the same rule, and point the acceptance and CRUD fixtures at the project's implicit root "production" branch instead of a child branch. Co-authored-by: Isaac --- .../basic/databricks.yml.tmpl | 10 ++---- .../basic/out.requests.create.txt | 16 ++------- .../basic/out.requests.remove.txt | 14 ++------ .../basic/out.requests.update.txt | 14 ++------ .../basic/output.txt | 34 ++++++------------- .../postgres_snapshot_schedules/basic/script | 2 +- .../out-of-band/databricks.yml.tmpl | 10 ++---- .../out-of-band/output.txt | 26 ++++++-------- .../out-of-band/script | 2 +- bundle/direct/dresources/all_test.go | 15 ++------ libs/testserver/postgres.go | 9 ++++- 11 files changed, 48 insertions(+), 104 deletions(-) diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/databricks.yml.tmpl b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/databricks.yml.tmpl index a951ec2a7cd..7b23ed6078f 100644 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/databricks.yml.tmpl +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/databricks.yml.tmpl @@ -11,15 +11,11 @@ resources: display_name: "Test Project for Snapshot Schedules" pg_version: 16 - postgres_branches: - main: - parent: ${resources.postgres_projects.my_project.id} - branch_id: main - no_expiry: true - postgres_snapshot_schedules: main_schedule: - branch: ${resources.postgres_branches.main.id} + # Snapshots are only allowed on the project's root branch (the implicitly + # created "production" branch). + branch: ${resources.postgres_projects.my_project.id}/branches/production schedule: - daily_schedule: hour: 3 diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.create.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.create.txt index 28332f384de..7a674e8d1bc 100644 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.create.txt +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.create.txt @@ -1,10 +1,10 @@ { "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule" } { "method": "PATCH", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule", "q": { "update_mask": "schedule" }, @@ -32,15 +32,3 @@ } } } -{ - "method": "POST", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches", - "q": { - "branch_id": "main" - }, - "body": { - "spec": { - "no_expiry": true - } - } -} diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.remove.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.remove.txt index 9b0ebd46820..8449f260878 100644 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.remove.txt +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.remove.txt @@ -4,23 +4,15 @@ } { "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule" } { "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule" } { "method": "PATCH", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule", "q": { "update_mask": "schedule" }, diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.update.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.update.txt index dcaaf4977e1..75841ac1e2a 100644 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.update.txt +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/out.requests.update.txt @@ -8,23 +8,15 @@ } { "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main" + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule" } { "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" -} -{ - "method": "GET", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule" + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule" } { "method": "PATCH", - "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "path": "/api/2.0/postgres/projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule", "q": { "update_mask": "schedule" }, diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/output.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/output.txt index c7eff1ef484..c0ecf60045f 100644 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/output.txt +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/output.txt @@ -2,15 +2,14 @@ === Create with a snapshot schedule >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-basic-[UNIQUE_NAME]/default/files... -Created postgres_branches.main Created postgres_projects.my_project Created postgres_snapshot_schedules.main_schedule Files: 0 uploaded, 0 deleted -Resources: 3 created, 0 changed, 0 deleted, 0 unchanged +Resources: 2 created, 0 changed, 0 deleted, 0 unchanged ->>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule +>>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule { - "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule", "schedule": [ { "daily_schedule": { @@ -26,11 +25,11 @@ Resources: 3 created, 0 changed, 0 deleted, 0 unchanged Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-basic-[UNIQUE_NAME]/default/files... Updated postgres_snapshot_schedules.main_schedule Files: 0 uploaded, 0 deleted -Resources: 0 created, 1 changed, 0 deleted, 2 unchanged +Resources: 0 created, 1 changed, 0 deleted, 1 unchanged ->>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule +>>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule { - "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule", "schedule": [ { "daily_schedule": { @@ -56,42 +55,31 @@ resources: display_name: "Test Project for Snapshot Schedules" pg_version: 16 - postgres_branches: - main: - parent: ${resources.postgres_projects.my_project.id} - branch_id: main - no_expiry: true - >>> [CLI] bundle deploy --auto-approve Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-basic-[UNIQUE_NAME]/default/files... Deleted postgres_snapshot_schedules.main_schedule Files: 0 uploaded, 0 deleted -Resources: 0 created, 0 changed, 1 deleted, 2 unchanged +Resources: 0 created, 0 changed, 1 deleted, 1 unchanged ->>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule +>>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule { - "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule", "schedule": null } === Plan again to confirm no drift after removal >>> [CLI] bundle plan -Plan: 0 to add, 0 to change, 0 to delete, 2 unchanged +Plan: 0 to add, 0 to change, 0 to delete, 1 unchanged >>> [CLI] bundle destroy --auto-approve The following resources will be deleted: - delete resources.postgres_branches.main delete resources.postgres_projects.my_project This action will result in the deletion of the following Lakebase projects along with all their branches, databases, and endpoints. All data stored in them will be permanently lost: delete resources.postgres_projects.my_project -This action will result in the deletion of the following Lakebase branches. -All data stored in them will be permanently lost: - delete resources.postgres_branches.main - All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-basic-[UNIQUE_NAME]/default -Destroy: 2 deleted +Destroy: 1 deleted diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/script b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/script index 77c51554a9d..856fbfe2ee0 100644 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/basic/script +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/basic/script @@ -4,7 +4,7 @@ cleanup() { } trap cleanup EXIT -schedule_name="projects/test-pg-proj-${UNIQUE_NAME}/branches/main/snapshot-schedule" +schedule_name="projects/test-pg-proj-${UNIQUE_NAME}/branches/production/snapshot-schedule" title "Create with a snapshot schedule" envsubst < databricks.yml.tmpl > databricks.yml diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/databricks.yml.tmpl b/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/databricks.yml.tmpl index e24897277b9..110aaa95432 100644 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/databricks.yml.tmpl +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/databricks.yml.tmpl @@ -11,15 +11,11 @@ resources: display_name: "Test Project for Snapshot Schedules" pg_version: 16 - postgres_branches: - main: - parent: ${resources.postgres_projects.my_project.id} - branch_id: main - no_expiry: true - postgres_snapshot_schedules: main_schedule: - branch: ${resources.postgres_branches.main.id} + # Snapshots are only allowed on the project's root branch (the implicitly + # created "production" branch). + branch: ${resources.postgres_projects.my_project.id}/branches/production schedule: - daily_schedule: hour: 3 diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/output.txt b/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/output.txt index 41786d6076c..e11ac76f602 100644 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/output.txt +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/output.txt @@ -2,15 +2,14 @@ === Deploy with a snapshot schedule >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-oob-[UNIQUE_NAME]/default/files... -Created postgres_branches.main Created postgres_projects.my_project Created postgres_snapshot_schedules.main_schedule Files: 0 uploaded, 0 deleted -Resources: 3 created, 0 changed, 0 deleted, 0 unchanged +Resources: 2 created, 0 changed, 0 deleted, 0 unchanged ->>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule +>>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule { - "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule", "schedule": [ { "daily_schedule": { @@ -22,9 +21,9 @@ Resources: 3 created, 0 changed, 0 deleted, 0 unchanged } === Change the schedule out of band via a direct API call ->>> [CLI] postgres update-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule schedule --json {"schedule":[{"daily_schedule":{"hour":9},"retention":"604800s"}]} +>>> [CLI] postgres update-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule schedule --json {"schedule":[{"daily_schedule":{"hour":9},"retention":"604800s"}]} { - "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule", "schedule": [ { "daily_schedule": { @@ -39,18 +38,18 @@ Resources: 3 created, 0 changed, 0 deleted, 0 unchanged >>> [CLI] bundle plan update postgres_snapshot_schedules.main_schedule -Plan: 0 to add, 1 to change, 0 to delete, 2 unchanged +Plan: 0 to add, 1 to change, 0 to delete, 1 unchanged === Deploy reconciles the schedule back to the configured cadence >>> [CLI] bundle deploy --auto-approve Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-oob-[UNIQUE_NAME]/default/files... Updated postgres_snapshot_schedules.main_schedule Files: 0 uploaded, 0 deleted -Resources: 0 created, 1 changed, 0 deleted, 2 unchanged +Resources: 0 created, 1 changed, 0 deleted, 1 unchanged ->>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule +>>> [CLI] postgres get-snapshot-schedule projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule { - "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/main/snapshot-schedule", + "name": "projects/test-pg-proj-[UNIQUE_NAME]/branches/production/snapshot-schedule", "schedule": [ { "daily_schedule": { @@ -63,7 +62,6 @@ Resources: 0 created, 1 changed, 0 deleted, 2 unchanged >>> [CLI] bundle destroy --auto-approve The following resources will be deleted: - delete resources.postgres_branches.main delete resources.postgres_projects.my_project delete resources.postgres_snapshot_schedules.main_schedule @@ -71,10 +69,6 @@ This action will result in the deletion of the following Lakebase projects along all their branches, databases, and endpoints. All data stored in them will be permanently lost: delete resources.postgres_projects.my_project -This action will result in the deletion of the following Lakebase branches. -All data stored in them will be permanently lost: - delete resources.postgres_branches.main - All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/deploy-pg-ss-oob-[UNIQUE_NAME]/default -Destroy: 3 deleted +Destroy: 2 deleted diff --git a/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/script b/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/script index 59d2cf6254e..b97e30fd848 100644 --- a/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/script +++ b/acceptance/bundle/resources/postgres_snapshot_schedules/out-of-band/script @@ -4,7 +4,7 @@ cleanup() { } trap cleanup EXIT -schedule_name="projects/test-pg-proj-${UNIQUE_NAME}/branches/main/snapshot-schedule" +schedule_name="projects/test-pg-proj-${UNIQUE_NAME}/branches/production/snapshot-schedule" title "Deploy with a snapshot schedule" envsubst < databricks.yml.tmpl > databricks.yml diff --git a/bundle/direct/dresources/all_test.go b/bundle/direct/dresources/all_test.go index 9eb7405e7cf..a881dc1d471 100644 --- a/bundle/direct/dresources/all_test.go +++ b/bundle/direct/dresources/all_test.go @@ -782,7 +782,8 @@ var testDeps = map[string]prepareWorkspace{ }, "postgres_snapshot_schedules": func(ctx context.Context, client *databricks.WorkspaceClient) (any, error) { - // Create parent project first + // Creating the project implicitly provisions the root "production" + // branch, the only branch a snapshot schedule may target. _, err := client.Postgres.CreateProject(ctx, postgres.CreateProjectRequest{ ProjectId: "test-project-for-snapshot-schedule", Project: postgres.Project{ @@ -796,19 +797,9 @@ var testDeps = map[string]prepareWorkspace{ return nil, err } - // Create parent branch - _, err = client.Postgres.CreateBranch(ctx, postgres.CreateBranchRequest{ - Parent: "projects/test-project-for-snapshot-schedule", - BranchId: "test-branch-for-snapshot-schedule", - Branch: postgres.Branch{}, - }) - if err != nil { - return nil, err - } - return &resources.PostgresSnapshotSchedule{ PostgresSnapshotScheduleConfig: resources.PostgresSnapshotScheduleConfig{ - Branch: "projects/test-project-for-snapshot-schedule/branches/test-branch-for-snapshot-schedule", + Branch: "projects/test-project-for-snapshot-schedule/branches/production", }, }, nil }, diff --git a/libs/testserver/postgres.go b/libs/testserver/postgres.go index 752b178a6c4..2c69b2536b3 100644 --- a/libs/testserver/postgres.go +++ b/libs/testserver/postgres.go @@ -550,10 +550,17 @@ func (s *FakeWorkspace) PostgresSnapshotScheduleUpdate(req Request, name string) defer s.LockUnlock()() branchName := strings.TrimSuffix(name, "/snapshot-schedule") - if _, exists := s.PostgresBranches[branchName]; !exists { + branch, exists := s.PostgresBranches[branchName] + if !exists { return postgresNotFoundResponse("branch") } + // Snapshots are only allowed on the root (default) branch; the backend + // rejects a schedule on any branch created off another. + if branch.Status == nil || !branch.Status.Default { + return postgresErrorResponse(400, "BAD_REQUEST", "not allowed to snapshot non-root branch") + } + var updateSchedule postgres.SnapshotSchedule if len(req.Body) > 0 { if err := json.Unmarshal(req.Body, &updateSchedule); err != nil { From 1cb15f6cee44c1f4c07d086eb3db34a2c8ffcbae Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Tue, 8 Sep 2026 17:08:09 +0000 Subject: [PATCH 16/22] Expose the snapshot schedule name via GetName The schedule's resource name is its ID ("{branch}/snapshot-schedule"); return it from GetName so bundle summary shows it instead of a blank, matching the SecretScope precedent (per review feedback). Co-authored-by: Isaac --- .../deployment/bind/postgres_snapshot_schedule/output.txt | 2 +- bundle/config/resources/postgres_snapshot_schedule.go | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt index 71102ecfd2c..8701019ab60 100644 --- a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt +++ b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt @@ -12,7 +12,7 @@ Workspace: Resources: Postgres snapshot schedules: schedule1: - Name: + Name: projects/test-project/branches/main/snapshot-schedule URL: (not deployed) >>> [CLI] bundle deployment unbind schedule1 diff --git a/bundle/config/resources/postgres_snapshot_schedule.go b/bundle/config/resources/postgres_snapshot_schedule.go index 6c0d353429f..cc35d357417 100644 --- a/bundle/config/resources/postgres_snapshot_schedule.go +++ b/bundle/config/resources/postgres_snapshot_schedule.go @@ -67,8 +67,9 @@ func (b *PostgresSnapshotSchedule) ResourceDescription() ResourceDescription { } func (b *PostgresSnapshotSchedule) GetName() string { - // Snapshot schedules don't have a user-visible name field. - return "" + // The schedule has no name field of its own; its resource name is its ID + // ("{branch}/snapshot-schedule"). + return b.ID } func (b *PostgresSnapshotSchedule) GetURL() string { From ea32dbc578c2089d85c70ec4c5a9c4768a8057ad Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Wed, 9 Sep 2026 06:31:34 +0000 Subject: [PATCH 17/22] Regenerate PyDABs for postgres_snapshot_schedules The Python codegen had no mapping for duration.Duration (the schedule's retention type), failing pydabs-codegen with a KeyError. Treat it as a str-serialized primitive, matching time.Time (PRIMITIVES + RENAMES + the test-case synthesizer), and regenerate the PyDABs module. Add the required acceptance/bundle/python support fixture and refresh the core public-API snapshot. Co-authored-by: Isaac --- .../databricks.yml | 19 +++ .../mutators.py | 13 ++ .../out.test.toml | 4 + .../output.txt | 40 ++++++ .../resources.py | 20 +++ .../script | 5 + .../test.toml | 7 + .../codegen/codegen/generated_test_cases.py | 3 + python/codegen/codegen/packages.py | 3 + python/databricks/bundles/core/__init__.py | 2 + .../bundles/core/_generated/__init__.py | 8 ++ .../_generated/postgres_snapshot_schedules.py | 132 ++++++++++++++++++ .../postgres_snapshot_schedules/__init__.py | 60 ++++++++ .../_models/daily_schedule.py | 48 +++++++ .../_models/day_of_week.py | 28 ++++ .../_models/lifecycle.py | 40 ++++++ .../_models/monthly_schedule.py | 66 +++++++++ .../_models/postgres_snapshot_schedule.py | 73 ++++++++++ .../_models/schedule_cadence.py | 104 ++++++++++++++ .../_models/weekly_schedule.py | 66 +++++++++ .../core/_generated/__init__.py | 2 + .../_generated/postgres_snapshot_schedules.py | 34 +++++ python/databricks_tests/core/public_api.txt | 8 ++ 23 files changed, 785 insertions(+) create mode 100644 acceptance/bundle/python/postgres_snapshot_schedules-support/databricks.yml create mode 100644 acceptance/bundle/python/postgres_snapshot_schedules-support/mutators.py create mode 100644 acceptance/bundle/python/postgres_snapshot_schedules-support/out.test.toml create mode 100644 acceptance/bundle/python/postgres_snapshot_schedules-support/output.txt create mode 100644 acceptance/bundle/python/postgres_snapshot_schedules-support/resources.py create mode 100644 acceptance/bundle/python/postgres_snapshot_schedules-support/script create mode 100644 acceptance/bundle/python/postgres_snapshot_schedules-support/test.toml create mode 100644 python/databricks/bundles/core/_generated/postgres_snapshot_schedules.py create mode 100644 python/databricks/bundles/postgres_snapshot_schedules/__init__.py create mode 100644 python/databricks/bundles/postgres_snapshot_schedules/_models/daily_schedule.py create mode 100644 python/databricks/bundles/postgres_snapshot_schedules/_models/day_of_week.py create mode 100644 python/databricks/bundles/postgres_snapshot_schedules/_models/lifecycle.py create mode 100644 python/databricks/bundles/postgres_snapshot_schedules/_models/monthly_schedule.py create mode 100644 python/databricks/bundles/postgres_snapshot_schedules/_models/postgres_snapshot_schedule.py create mode 100644 python/databricks/bundles/postgres_snapshot_schedules/_models/schedule_cadence.py create mode 100644 python/databricks/bundles/postgres_snapshot_schedules/_models/weekly_schedule.py create mode 100644 python/databricks_tests/core/_generated/postgres_snapshot_schedules.py diff --git a/acceptance/bundle/python/postgres_snapshot_schedules-support/databricks.yml b/acceptance/bundle/python/postgres_snapshot_schedules-support/databricks.yml new file mode 100644 index 00000000000..ee4c39906b8 --- /dev/null +++ b/acceptance/bundle/python/postgres_snapshot_schedules-support/databricks.yml @@ -0,0 +1,19 @@ +bundle: + name: my_project + +sync: {paths: []} # don't need to copy files + +python: + resources: + - "resources:load_resources" + mutators: + - "mutators:update_postgres_snapshot_schedule" + +resources: + postgres_snapshot_schedules: + my_snapshot_schedule_1: + branch: "projects/test-project/branches/production" + schedule: + - retention: "604800s" + daily_schedule: + hour: 3 diff --git a/acceptance/bundle/python/postgres_snapshot_schedules-support/mutators.py b/acceptance/bundle/python/postgres_snapshot_schedules-support/mutators.py new file mode 100644 index 00000000000..5dbadf211ea --- /dev/null +++ b/acceptance/bundle/python/postgres_snapshot_schedules-support/mutators.py @@ -0,0 +1,13 @@ +from dataclasses import replace + +from databricks.bundles.core import postgres_snapshot_schedule_mutator +from databricks.bundles.postgres_snapshot_schedules import PostgresSnapshotSchedule + + +@postgres_snapshot_schedule_mutator +def update_postgres_snapshot_schedule( + schedule: PostgresSnapshotSchedule, +) -> PostgresSnapshotSchedule: + assert isinstance(schedule.branch, str) + + return replace(schedule, branch=f"{schedule.branch} (updated)") diff --git a/acceptance/bundle/python/postgres_snapshot_schedules-support/out.test.toml b/acceptance/bundle/python/postgres_snapshot_schedules-support/out.test.toml new file mode 100644 index 00000000000..8feac676720 --- /dev/null +++ b/acceptance/bundle/python/postgres_snapshot_schedules-support/out.test.toml @@ -0,0 +1,4 @@ +Cloud = false +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] +EnvMatrix.DMS = ["", "true"] +EnvMatrix.PYDAB_VERSION = ["current"] diff --git a/acceptance/bundle/python/postgres_snapshot_schedules-support/output.txt b/acceptance/bundle/python/postgres_snapshot_schedules-support/output.txt new file mode 100644 index 00000000000..f02cc4ca7f3 --- /dev/null +++ b/acceptance/bundle/python/postgres_snapshot_schedules-support/output.txt @@ -0,0 +1,40 @@ + +>>> uv run [UV_ARGS] -q [CLI] bundle validate --output json +{ + "experimental": { + "python": { + "mutators": [ + "mutators:update_postgres_snapshot_schedule" + ], + "resources": [ + "resources:load_resources" + ] + } + }, + "resources": { + "postgres_snapshot_schedules": { + "my_snapshot_schedule_1": { + "branch": "projects/test-project/branches/production (updated)", + "schedule": [ + { + "daily_schedule": { + "hour": 3 + }, + "retention": "604800s" + } + ] + }, + "my_snapshot_schedule_2": { + "branch": "projects/other-project/branches/production (updated)", + "schedule": [ + { + "daily_schedule": { + "hour": 5 + }, + "retention": "604800s" + } + ] + } + } + } +} diff --git a/acceptance/bundle/python/postgres_snapshot_schedules-support/resources.py b/acceptance/bundle/python/postgres_snapshot_schedules-support/resources.py new file mode 100644 index 00000000000..d34c47a0013 --- /dev/null +++ b/acceptance/bundle/python/postgres_snapshot_schedules-support/resources.py @@ -0,0 +1,20 @@ +from databricks.bundles.core import Resources + + +def load_resources() -> Resources: + resources = Resources() + + resources.add_postgres_snapshot_schedule( + "my_snapshot_schedule_2", + { + "branch": "projects/other-project/branches/production", + "schedule": [ + { + "retention": "604800s", + "daily_schedule": {"hour": 5}, + }, + ], + }, + ) + + return resources diff --git a/acceptance/bundle/python/postgres_snapshot_schedules-support/script b/acceptance/bundle/python/postgres_snapshot_schedules-support/script new file mode 100644 index 00000000000..e273fb45a53 --- /dev/null +++ b/acceptance/bundle/python/postgres_snapshot_schedules-support/script @@ -0,0 +1,5 @@ + +trace uv run $UV_ARGS -q $CLI bundle validate --output json | \ + jq "pick(.experimental.python, .resources)" + +rm -fr .databricks __pycache__ diff --git a/acceptance/bundle/python/postgres_snapshot_schedules-support/test.toml b/acceptance/bundle/python/postgres_snapshot_schedules-support/test.toml new file mode 100644 index 00000000000..d2430be4bd4 --- /dev/null +++ b/acceptance/bundle/python/postgres_snapshot_schedules-support/test.toml @@ -0,0 +1,7 @@ +Cloud = false # tests do not interact with APIs + +# postgres_snapshot_schedules only exist in the current version of the wheel +EnvMatrix.PYDAB_VERSION = ["current"] + +# postgres_snapshot_schedules are only supported on the direct deployment engine +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/python/codegen/codegen/generated_test_cases.py b/python/codegen/codegen/generated_test_cases.py index a19506343fe..aa030f5f49e 100644 --- a/python/codegen/codegen/generated_test_cases.py +++ b/python/codegen/codegen/generated_test_cases.py @@ -120,6 +120,9 @@ def _synth_scalar(name: str, hint: str) -> _Scalar: # time.Time is generated as a str (see packages.RENAMES); serialized as RFC3339. if name == "time.Time": return _Scalar('"2020-01-01T00:00:00Z"', '"2020-01-01T00:00:00Z"') + # duration.Duration is generated as a str; serialized as a seconds string. + if name == "duration.Duration": + return _Scalar('"3600s"', '"3600s"') raise ValueError(f"Unknown primitive: {name}") diff --git a/python/codegen/codegen/packages.py b/python/codegen/codegen/packages.py index 6155a94c8a7..9a0b6a76188 100644 --- a/python/codegen/codegen/packages.py +++ b/python/codegen/codegen/packages.py @@ -65,6 +65,8 @@ def _load_resource_namespace() -> dict[str, str]: # time.Time is a scalar serialized as an RFC3339 string; the Go side models # it as a string too (see libs/dyn/convert/sdk_native_types.go). "time.Time": "str", + # duration.Duration is a scalar serialized as a seconds string (e.g. "3600s"). + "duration.Duration": "str", "string": "str", "boolean": "bool", "integer": "int", @@ -76,6 +78,7 @@ def _load_resource_namespace() -> dict[str, str]: PRIMITIVES = [ # Treated as str "time.Time", + "duration.Duration", "string", "boolean", "integer", diff --git a/python/databricks/bundles/core/__init__.py b/python/databricks/bundles/core/__init__.py index a84a2e084d3..bf0fd205dc5 100644 --- a/python/databricks/bundles/core/__init__.py +++ b/python/databricks/bundles/core/__init__.py @@ -32,6 +32,7 @@ "mlflow_model_mutator", "model_serving_endpoint_mutator", "pipeline_mutator", + "postgres_snapshot_schedule_mutator", "quality_monitor_mutator", "registered_model_mutator", "schema_mutator", @@ -66,6 +67,7 @@ mlflow_model_mutator, model_serving_endpoint_mutator, pipeline_mutator, + postgres_snapshot_schedule_mutator, quality_monitor_mutator, registered_model_mutator, schema_mutator, diff --git a/python/databricks/bundles/core/_generated/__init__.py b/python/databricks/bundles/core/_generated/__init__.py index cd6ca9f035b..a28d59b6c7d 100644 --- a/python/databricks/bundles/core/_generated/__init__.py +++ b/python/databricks/bundles/core/_generated/__init__.py @@ -49,6 +49,10 @@ _PipelineResources, pipeline_mutator, ) +from databricks.bundles.core._generated.postgres_snapshot_schedules import ( + _PostgresSnapshotScheduleResources, + postgres_snapshot_schedule_mutator, +) from databricks.bundles.core._generated.quality_monitors import ( _QualityMonitorResources, quality_monitor_mutator, @@ -101,6 +105,7 @@ "mlflow_model_mutator", "model_serving_endpoint_mutator", "pipeline_mutator", + "postgres_snapshot_schedule_mutator", "quality_monitor_mutator", "registered_model_mutator", "schema_mutator", @@ -129,6 +134,7 @@ class _GeneratedResources( _ModelServingEndpointResources, _MlflowModelResources, _PipelineResources, + _PostgresSnapshotScheduleResources, _QualityMonitorResources, _RegisteredModelResources, _SchemaResources, @@ -159,6 +165,7 @@ def _all_resource_types() -> "tuple[_ResourceType, ...]": model_serving_endpoints, models, pipelines, + postgres_snapshot_schedules, quality_monitors, registered_models, schemas, @@ -186,6 +193,7 @@ def _all_resource_types() -> "tuple[_ResourceType, ...]": model_serving_endpoints._resource_type(), models._resource_type(), pipelines._resource_type(), + postgres_snapshot_schedules._resource_type(), quality_monitors._resource_type(), registered_models._resource_type(), schemas._resource_type(), diff --git a/python/databricks/bundles/core/_generated/postgres_snapshot_schedules.py b/python/databricks/bundles/core/_generated/postgres_snapshot_schedules.py new file mode 100644 index 00000000000..ff2a3cd2959 --- /dev/null +++ b/python/databricks/bundles/core/_generated/postgres_snapshot_schedules.py @@ -0,0 +1,132 @@ +# Code generated by pydabs-codegen. DO NOT EDIT. + +from collections.abc import Callable +from typing import TYPE_CHECKING, Optional, overload + +from databricks.bundles.core._bundle import Bundle +from databricks.bundles.core._location import Location +from databricks.bundles.core._resource_mutator import ResourceMutator +from databricks.bundles.core._transform import _transform + +if TYPE_CHECKING: + from databricks.bundles.core._resource_type import _ResourceType + from databricks.bundles.postgres_snapshot_schedules._models.postgres_snapshot_schedule import ( + PostgresSnapshotSchedule, + PostgresSnapshotScheduleParam, + ) + + +def _resource_type() -> "_ResourceType": + from databricks.bundles.core._resource_type import _ResourceType + from databricks.bundles.postgres_snapshot_schedules._models.postgres_snapshot_schedule import ( + PostgresSnapshotSchedule, + ) + + return _ResourceType( + resource_type=PostgresSnapshotSchedule, + singular_name="postgres_snapshot_schedule", + plural_name="postgres_snapshot_schedules", + ) + + +class _PostgresSnapshotScheduleResources: + """ + Generated postgres_snapshot_schedule accessors, mixed into Resources. + """ + + # Provided by the Resources subclass; declared here so the generated methods + # below type-check. + _resources: dict[str, dict] + + if TYPE_CHECKING: + + def add_location(self, path: tuple[str, ...], location: Location) -> None: ... + + def add_diagnostic_error( + self, + msg: str, + *, + detail: Optional[str] = None, + path: Optional[tuple[str, ...]] = None, + location: Optional[Location] = None, + ) -> None: ... + + @property + def postgres_snapshot_schedules(self) -> dict[str, "PostgresSnapshotSchedule"]: + return self._resources["postgres_snapshot_schedules"] + + def add_postgres_snapshot_schedule( + self, + resource_name: str, + postgres_snapshot_schedule: "PostgresSnapshotScheduleParam", + *, + location: Optional[Location] = None, + ) -> None: + """ + Adds the resource postgres_snapshot_schedule to the collection of resources. Resource name must be unique across all postgres_snapshot_schedules. + + :param resource_name: unique identifier for the postgres_snapshot_schedule + :param postgres_snapshot_schedule: the postgres_snapshot_schedule to add, can be PostgresSnapshotSchedule or dict + :param location: optional location of the postgres_snapshot_schedule in the source code + """ + from databricks.bundles.postgres_snapshot_schedules._models.postgres_snapshot_schedule import ( + PostgresSnapshotSchedule, + ) + + postgres_snapshot_schedule = _transform( + PostgresSnapshotSchedule, postgres_snapshot_schedule + ) + path = ("resources", "postgres_snapshot_schedules", resource_name) + location = location or Location.from_stack_frame(depth=1) + + if self._resources["postgres_snapshot_schedules"].get(resource_name): + self.add_diagnostic_error( + msg=f"Duplicate resource name '{resource_name}' for resource 'postgres_snapshot_schedule'. Resource names must be unique.", + location=location, + path=path, + ) + else: + if location: + self.add_location(path, location) + + self._resources["postgres_snapshot_schedules"][resource_name] = ( + postgres_snapshot_schedule + ) + + +@overload +def postgres_snapshot_schedule_mutator( + function: Callable[ + [Bundle, "PostgresSnapshotSchedule"], "PostgresSnapshotSchedule" + ], +) -> ResourceMutator["PostgresSnapshotSchedule"]: ... + + +@overload +def postgres_snapshot_schedule_mutator( + function: Callable[["PostgresSnapshotSchedule"], "PostgresSnapshotSchedule"], +) -> ResourceMutator["PostgresSnapshotSchedule"]: ... + + +def postgres_snapshot_schedule_mutator( + function: Callable, +) -> ResourceMutator["PostgresSnapshotSchedule"]: + """ + Decorator for defining mutator for postgres_snapshot_schedules. Function should return a new instance of the postgres_snapshot_schedule + with the desired changes, instead of mutating the input postgres_snapshot_schedule. + + Example: + + .. code-block:: python + + @postgres_snapshot_schedule_mutator + def my_postgres_snapshot_schedule_mutator(bundle: Bundle, postgres_snapshot_schedule: PostgresSnapshotSchedule) -> PostgresSnapshotSchedule: + return replace(postgres_snapshot_schedule, ...) + + :param function: Function that mutates postgres_snapshot_schedules. + """ + from databricks.bundles.postgres_snapshot_schedules._models.postgres_snapshot_schedule import ( + PostgresSnapshotSchedule, + ) + + return ResourceMutator(resource_type=PostgresSnapshotSchedule, function=function) diff --git a/python/databricks/bundles/postgres_snapshot_schedules/__init__.py b/python/databricks/bundles/postgres_snapshot_schedules/__init__.py new file mode 100644 index 00000000000..7abbe1eb900 --- /dev/null +++ b/python/databricks/bundles/postgres_snapshot_schedules/__init__.py @@ -0,0 +1,60 @@ +# Code generated by pydabs-codegen. DO NOT EDIT. + +__all__ = [ + "DailySchedule", + "DailyScheduleDict", + "DailyScheduleParam", + "DayOfWeek", + "DayOfWeekParam", + "Lifecycle", + "LifecycleDict", + "LifecycleParam", + "MonthlySchedule", + "MonthlyScheduleDict", + "MonthlyScheduleParam", + "PostgresSnapshotSchedule", + "PostgresSnapshotScheduleDict", + "PostgresSnapshotScheduleParam", + "ScheduleCadence", + "ScheduleCadenceDict", + "ScheduleCadenceParam", + "WeeklySchedule", + "WeeklyScheduleDict", + "WeeklyScheduleParam", +] + + +from databricks.bundles.postgres_snapshot_schedules._models.daily_schedule import ( + DailySchedule, + DailyScheduleDict, + DailyScheduleParam, +) +from databricks.bundles.postgres_snapshot_schedules._models.day_of_week import ( + DayOfWeek, + DayOfWeekParam, +) +from databricks.bundles.postgres_snapshot_schedules._models.lifecycle import ( + Lifecycle, + LifecycleDict, + LifecycleParam, +) +from databricks.bundles.postgres_snapshot_schedules._models.monthly_schedule import ( + MonthlySchedule, + MonthlyScheduleDict, + MonthlyScheduleParam, +) +from databricks.bundles.postgres_snapshot_schedules._models.postgres_snapshot_schedule import ( + PostgresSnapshotSchedule, + PostgresSnapshotScheduleDict, + PostgresSnapshotScheduleParam, +) +from databricks.bundles.postgres_snapshot_schedules._models.schedule_cadence import ( + ScheduleCadence, + ScheduleCadenceDict, + ScheduleCadenceParam, +) +from databricks.bundles.postgres_snapshot_schedules._models.weekly_schedule import ( + WeeklySchedule, + WeeklyScheduleDict, + WeeklyScheduleParam, +) diff --git a/python/databricks/bundles/postgres_snapshot_schedules/_models/daily_schedule.py b/python/databricks/bundles/postgres_snapshot_schedules/_models/daily_schedule.py new file mode 100644 index 00000000000..c81c9378614 --- /dev/null +++ b/python/databricks/bundles/postgres_snapshot_schedules/_models/daily_schedule.py @@ -0,0 +1,48 @@ +# Code generated by pydabs-codegen. DO NOT EDIT. + +from dataclasses import dataclass +from typing import TYPE_CHECKING, TypedDict + +from databricks.bundles.core._transform import _transform +from databricks.bundles.core._transform_to_json import _transform_to_json_value +from databricks.bundles.core._variable import VariableOrOptional + +if TYPE_CHECKING: + from typing_extensions import Self + + +@dataclass(kw_only=True) +class DailySchedule: + """ + :meta private: [EXPERIMENTAL] + + Take a snapshot once per day, at the configured hour. + """ + + hour: VariableOrOptional[int] = None + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] The hour of the day, in UTC, at which to take the snapshot, in [0, 23]. + """ + + @classmethod + def from_dict(cls, value: "DailyScheduleDict") -> "Self": + return _transform(cls, value) + + def as_dict(self) -> "DailyScheduleDict": + return _transform_to_json_value(self) # type:ignore + + +class DailyScheduleDict(TypedDict, total=False): + """""" + + hour: VariableOrOptional[int] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] The hour of the day, in UTC, at which to take the snapshot, in [0, 23]. + """ + + +DailyScheduleParam = DailyScheduleDict | DailySchedule diff --git a/python/databricks/bundles/postgres_snapshot_schedules/_models/day_of_week.py b/python/databricks/bundles/postgres_snapshot_schedules/_models/day_of_week.py new file mode 100644 index 00000000000..8e18ca78a99 --- /dev/null +++ b/python/databricks/bundles/postgres_snapshot_schedules/_models/day_of_week.py @@ -0,0 +1,28 @@ +# Code generated by pydabs-codegen. DO NOT EDIT. + +from enum import Enum +from typing import Literal + + +class DayOfWeek(Enum): + """ + :meta private: [EXPERIMENTAL] + + The day of the week on which a weekly snapshot is taken. + """ + + MONDAY = "MONDAY" + TUESDAY = "TUESDAY" + WEDNESDAY = "WEDNESDAY" + THURSDAY = "THURSDAY" + FRIDAY = "FRIDAY" + SATURDAY = "SATURDAY" + SUNDAY = "SUNDAY" + + +DayOfWeekParam = ( + Literal[ + "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY" + ] + | DayOfWeek +) diff --git a/python/databricks/bundles/postgres_snapshot_schedules/_models/lifecycle.py b/python/databricks/bundles/postgres_snapshot_schedules/_models/lifecycle.py new file mode 100644 index 00000000000..697776a198e --- /dev/null +++ b/python/databricks/bundles/postgres_snapshot_schedules/_models/lifecycle.py @@ -0,0 +1,40 @@ +# Code generated by pydabs-codegen. DO NOT EDIT. + +from dataclasses import dataclass +from typing import TYPE_CHECKING, TypedDict + +from databricks.bundles.core._transform import _transform +from databricks.bundles.core._transform_to_json import _transform_to_json_value +from databricks.bundles.core._variable import VariableOrOptional + +if TYPE_CHECKING: + from typing_extensions import Self + + +@dataclass(kw_only=True) +class Lifecycle: + """""" + + prevent_destroy: VariableOrOptional[bool] = None + """ + Lifecycle setting to prevent the resource from being destroyed. + """ + + @classmethod + def from_dict(cls, value: "LifecycleDict") -> "Self": + return _transform(cls, value) + + def as_dict(self) -> "LifecycleDict": + return _transform_to_json_value(self) # type:ignore + + +class LifecycleDict(TypedDict, total=False): + """""" + + prevent_destroy: VariableOrOptional[bool] + """ + Lifecycle setting to prevent the resource from being destroyed. + """ + + +LifecycleParam = LifecycleDict | Lifecycle diff --git a/python/databricks/bundles/postgres_snapshot_schedules/_models/monthly_schedule.py b/python/databricks/bundles/postgres_snapshot_schedules/_models/monthly_schedule.py new file mode 100644 index 00000000000..8706a64478e --- /dev/null +++ b/python/databricks/bundles/postgres_snapshot_schedules/_models/monthly_schedule.py @@ -0,0 +1,66 @@ +# Code generated by pydabs-codegen. DO NOT EDIT. + +from dataclasses import dataclass +from typing import TYPE_CHECKING, TypedDict + +from databricks.bundles.core._transform import _transform +from databricks.bundles.core._transform_to_json import _transform_to_json_value +from databricks.bundles.core._variable import VariableOr, VariableOrOptional + +if TYPE_CHECKING: + from typing_extensions import Self + + +@dataclass(kw_only=True) +class MonthlySchedule: + """ + :meta private: [EXPERIMENTAL] + + Take a snapshot once per month, on the configured day at the configured hour. + """ + + day: VariableOr[int] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] The day of the month on which to take the snapshot, in [1, 31]. In shorter + months the snapshot is taken on the last day instead (day 31 runs on Feb 28 + or 29, and on Apr 30), so every month gets exactly one snapshot. + """ + + hour: VariableOrOptional[int] = None + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] The hour of the day, in UTC, at which to take the snapshot, in [0, 23]. + """ + + @classmethod + def from_dict(cls, value: "MonthlyScheduleDict") -> "Self": + return _transform(cls, value) + + def as_dict(self) -> "MonthlyScheduleDict": + return _transform_to_json_value(self) # type:ignore + + +class MonthlyScheduleDict(TypedDict, total=False): + """""" + + day: VariableOr[int] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] The day of the month on which to take the snapshot, in [1, 31]. In shorter + months the snapshot is taken on the last day instead (day 31 runs on Feb 28 + or 29, and on Apr 30), so every month gets exactly one snapshot. + """ + + hour: VariableOrOptional[int] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] The hour of the day, in UTC, at which to take the snapshot, in [0, 23]. + """ + + +MonthlyScheduleParam = MonthlyScheduleDict | MonthlySchedule diff --git a/python/databricks/bundles/postgres_snapshot_schedules/_models/postgres_snapshot_schedule.py b/python/databricks/bundles/postgres_snapshot_schedules/_models/postgres_snapshot_schedule.py new file mode 100644 index 00000000000..cfa3baf67ff --- /dev/null +++ b/python/databricks/bundles/postgres_snapshot_schedules/_models/postgres_snapshot_schedule.py @@ -0,0 +1,73 @@ +# Code generated by pydabs-codegen. DO NOT EDIT. + +from dataclasses import dataclass, field +from typing import TYPE_CHECKING, TypedDict + +from databricks.bundles.core._resource import Resource +from databricks.bundles.core._transform import _transform +from databricks.bundles.core._transform_to_json import _transform_to_json_value +from databricks.bundles.core._variable import ( + VariableOr, + VariableOrList, + VariableOrOptional, +) +from databricks.bundles.postgres_snapshot_schedules._models.lifecycle import ( + Lifecycle, + LifecycleParam, +) +from databricks.bundles.postgres_snapshot_schedules._models.schedule_cadence import ( + ScheduleCadence, + ScheduleCadenceParam, +) + +if TYPE_CHECKING: + from typing_extensions import Self + + +@dataclass(kw_only=True) +class PostgresSnapshotSchedule(Resource): + """""" + + branch: VariableOr[str] + """ + The branch whose automatic-snapshot schedule this manages. Format: projects/{project_id}/branches/{branch_id} + """ + + lifecycle: VariableOrOptional[Lifecycle] = None + """ + Settings that control the deployment lifecycle of the resource, such as preventing it from being destroyed. + """ + + schedule: VariableOrList[ScheduleCadence] = field(default_factory=list) + """ + The cadences at which automatic snapshots are taken. An empty set disables automatic snapshots. When several cadences fire together, one snapshot is taken and retained for the longest of their retentions. + """ + + @classmethod + def from_dict(cls, value: "PostgresSnapshotScheduleDict") -> "Self": + return _transform(cls, value) + + def as_dict(self) -> "PostgresSnapshotScheduleDict": + return _transform_to_json_value(self) # type:ignore + + +class PostgresSnapshotScheduleDict(TypedDict, total=False): + """""" + + branch: VariableOr[str] + """ + The branch whose automatic-snapshot schedule this manages. Format: projects/{project_id}/branches/{branch_id} + """ + + lifecycle: VariableOrOptional[LifecycleParam] + """ + Settings that control the deployment lifecycle of the resource, such as preventing it from being destroyed. + """ + + schedule: VariableOrList[ScheduleCadenceParam] + """ + The cadences at which automatic snapshots are taken. An empty set disables automatic snapshots. When several cadences fire together, one snapshot is taken and retained for the longest of their retentions. + """ + + +PostgresSnapshotScheduleParam = PostgresSnapshotScheduleDict | PostgresSnapshotSchedule diff --git a/python/databricks/bundles/postgres_snapshot_schedules/_models/schedule_cadence.py b/python/databricks/bundles/postgres_snapshot_schedules/_models/schedule_cadence.py new file mode 100644 index 00000000000..76e919c0dc6 --- /dev/null +++ b/python/databricks/bundles/postgres_snapshot_schedules/_models/schedule_cadence.py @@ -0,0 +1,104 @@ +# Code generated by pydabs-codegen. DO NOT EDIT. + +from dataclasses import dataclass +from typing import TYPE_CHECKING, TypedDict + +from databricks.bundles.core._transform import _transform +from databricks.bundles.core._transform_to_json import _transform_to_json_value +from databricks.bundles.core._variable import VariableOr, VariableOrOptional +from databricks.bundles.postgres_snapshot_schedules._models.daily_schedule import ( + DailySchedule, + DailyScheduleParam, +) +from databricks.bundles.postgres_snapshot_schedules._models.monthly_schedule import ( + MonthlySchedule, + MonthlyScheduleParam, +) +from databricks.bundles.postgres_snapshot_schedules._models.weekly_schedule import ( + WeeklySchedule, + WeeklyScheduleParam, +) + +if TYPE_CHECKING: + from typing_extensions import Self + + +@dataclass(kw_only=True) +class ScheduleCadence: + """ + One cadence at which automatic snapshots are taken. + """ + + retention: VariableOr[str] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] How long snapshots from this cadence are kept before automatic deletion. + Must be at least 1 hour. Applied when a snapshot is taken; not retroactive, + so changing it affects only later snapshots. + """ + + daily_schedule: VariableOrOptional[DailySchedule] = None + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] Take a snapshot once per day. + """ + + monthly_schedule: VariableOrOptional[MonthlySchedule] = None + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] Take a snapshot once per month. + """ + + weekly_schedule: VariableOrOptional[WeeklySchedule] = None + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] Take a snapshot once per week. + """ + + @classmethod + def from_dict(cls, value: "ScheduleCadenceDict") -> "Self": + return _transform(cls, value) + + def as_dict(self) -> "ScheduleCadenceDict": + return _transform_to_json_value(self) # type:ignore + + +class ScheduleCadenceDict(TypedDict, total=False): + """""" + + retention: VariableOr[str] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] How long snapshots from this cadence are kept before automatic deletion. + Must be at least 1 hour. Applied when a snapshot is taken; not retroactive, + so changing it affects only later snapshots. + """ + + daily_schedule: VariableOrOptional[DailyScheduleParam] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] Take a snapshot once per day. + """ + + monthly_schedule: VariableOrOptional[MonthlyScheduleParam] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] Take a snapshot once per month. + """ + + weekly_schedule: VariableOrOptional[WeeklyScheduleParam] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] Take a snapshot once per week. + """ + + +ScheduleCadenceParam = ScheduleCadenceDict | ScheduleCadence diff --git a/python/databricks/bundles/postgres_snapshot_schedules/_models/weekly_schedule.py b/python/databricks/bundles/postgres_snapshot_schedules/_models/weekly_schedule.py new file mode 100644 index 00000000000..0e6426ff9a4 --- /dev/null +++ b/python/databricks/bundles/postgres_snapshot_schedules/_models/weekly_schedule.py @@ -0,0 +1,66 @@ +# Code generated by pydabs-codegen. DO NOT EDIT. + +from dataclasses import dataclass +from typing import TYPE_CHECKING, TypedDict + +from databricks.bundles.core._transform import _transform +from databricks.bundles.core._transform_to_json import _transform_to_json_value +from databricks.bundles.core._variable import VariableOr, VariableOrOptional +from databricks.bundles.postgres_snapshot_schedules._models.day_of_week import ( + DayOfWeek, + DayOfWeekParam, +) + +if TYPE_CHECKING: + from typing_extensions import Self + + +@dataclass(kw_only=True) +class WeeklySchedule: + """ + :meta private: [EXPERIMENTAL] + + Take a snapshot once per week, on the configured day at the configured hour. + """ + + day_of_week: VariableOr[DayOfWeek] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] The day of the week on which to take the snapshot. + """ + + hour: VariableOrOptional[int] = None + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] The hour of the day, in UTC, at which to take the snapshot, in [0, 23]. + """ + + @classmethod + def from_dict(cls, value: "WeeklyScheduleDict") -> "Self": + return _transform(cls, value) + + def as_dict(self) -> "WeeklyScheduleDict": + return _transform_to_json_value(self) # type:ignore + + +class WeeklyScheduleDict(TypedDict, total=False): + """""" + + day_of_week: VariableOr[DayOfWeekParam] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] The day of the week on which to take the snapshot. + """ + + hour: VariableOrOptional[int] + """ + :meta private: [EXPERIMENTAL] + + [Private Preview] The hour of the day, in UTC, at which to take the snapshot, in [0, 23]. + """ + + +WeeklyScheduleParam = WeeklyScheduleDict | WeeklySchedule diff --git a/python/databricks_tests/core/_generated/__init__.py b/python/databricks_tests/core/_generated/__init__.py index 138ed2e29ef..fca10520617 100644 --- a/python/databricks_tests/core/_generated/__init__.py +++ b/python/databricks_tests/core/_generated/__init__.py @@ -15,6 +15,7 @@ model_serving_endpoints, models, pipelines, + postgres_snapshot_schedules, quality_monitors, registered_models, schemas, @@ -44,6 +45,7 @@ model_serving_endpoints._test_case(), models._test_case(), pipelines._test_case(), + postgres_snapshot_schedules._test_case(), quality_monitors._test_case(), registered_models._test_case(), schemas._test_case(), diff --git a/python/databricks_tests/core/_generated/postgres_snapshot_schedules.py b/python/databricks_tests/core/_generated/postgres_snapshot_schedules.py new file mode 100644 index 00000000000..fae3360cd72 --- /dev/null +++ b/python/databricks_tests/core/_generated/postgres_snapshot_schedules.py @@ -0,0 +1,34 @@ +# Code generated by pydabs-codegen. DO NOT EDIT. + +from databricks.bundles.core import Resources, postgres_snapshot_schedule_mutator +from databricks.bundles.core._generated.postgres_snapshot_schedules import ( + _resource_type, +) +from databricks.bundles.postgres_snapshot_schedules._models.lifecycle import Lifecycle +from databricks.bundles.postgres_snapshot_schedules._models.postgres_snapshot_schedule import ( + PostgresSnapshotSchedule, +) +from databricks.bundles.postgres_snapshot_schedules._models.schedule_cadence import ( + ScheduleCadence, +) +from databricks_tests.core._resource_test_case import TestCase + + +def _test_case(): + return ( + TestCase( + add_resource=Resources.add_postgres_snapshot_schedule, + dict_example={ + "branch": "branch", + "lifecycle": {}, + "schedule": [{"retention": "3600s"}], + }, + dataclass_example=PostgresSnapshotSchedule( + branch="branch", + lifecycle=Lifecycle(), + schedule=[ScheduleCadence(retention="3600s")], + ), + mutator=postgres_snapshot_schedule_mutator, + ), + _resource_type(), + ) diff --git a/python/databricks_tests/core/public_api.txt b/python/databricks_tests/core/public_api.txt index f5bdf488418..05b42854dfa 100644 --- a/python/databricks_tests/core/public_api.txt +++ b/python/databricks_tests/core/public_api.txt @@ -31,6 +31,7 @@ __all__ = [ mlflow_model_mutator, model_serving_endpoint_mutator, pipeline_mutator, + postgres_snapshot_schedule_mutator, quality_monitor_mutator, registered_model_mutator, schema_mutator, @@ -101,6 +102,7 @@ class Resources: def add_mlflow_model(self, resource_name: str, mlflow_model: MlflowModelParam, *, location: Union[Location, None] = None) -> None def add_model_serving_endpoint(self, resource_name: str, model_serving_endpoint: ModelServingEndpointParam, *, location: Union[Location, None] = None) -> None def add_pipeline(self, resource_name: str, pipeline: PipelineParam, *, location: Union[Location, None] = None) -> None + def add_postgres_snapshot_schedule(self, resource_name: str, postgres_snapshot_schedule: PostgresSnapshotScheduleParam, *, location: Union[Location, None] = None) -> None def add_quality_monitor(self, resource_name: str, quality_monitor: QualityMonitorParam, *, location: Union[Location, None] = None) -> None def add_registered_model(self, resource_name: str, registered_model: RegisteredModelParam, *, location: Union[Location, None] = None) -> None def add_resource(self, resource_name: str, resource: Resource, *, location: Union[Location, None] = None) -> None @@ -128,6 +130,7 @@ class Resources: @property model_serving_endpoints -> dict[str, ModelServingEndpoint] @property models -> dict[str, MlflowModel] @property pipelines -> dict[str, Pipeline] + @property postgres_snapshot_schedules -> dict[str, PostgresSnapshotSchedule] @property quality_monitors -> dict[str, QualityMonitor] @property registered_models -> dict[str, RegisteredModel] @property schemas -> dict[str, Schema] @@ -220,6 +223,10 @@ def model_serving_endpoint_mutator(function: Callable) -> ResourceMutator[ModelS @overload def pipeline_mutator(function: Callable[[Pipeline], Pipeline]) -> ResourceMutator[Pipeline] def pipeline_mutator(function: Callable) -> ResourceMutator[Pipeline] +@overload def postgres_snapshot_schedule_mutator(function: Callable[[Bundle, PostgresSnapshotSchedule], PostgresSnapshotSchedule]) -> ResourceMutator[PostgresSnapshotSchedule] +@overload def postgres_snapshot_schedule_mutator(function: Callable[[PostgresSnapshotSchedule], PostgresSnapshotSchedule]) -> ResourceMutator[PostgresSnapshotSchedule] +def postgres_snapshot_schedule_mutator(function: Callable) -> ResourceMutator[PostgresSnapshotSchedule] + @overload def quality_monitor_mutator(function: Callable[[Bundle, QualityMonitor], QualityMonitor]) -> ResourceMutator[QualityMonitor] @overload def quality_monitor_mutator(function: Callable[[QualityMonitor], QualityMonitor]) -> ResourceMutator[QualityMonitor] def quality_monitor_mutator(function: Callable) -> ResourceMutator[QualityMonitor] @@ -277,6 +284,7 @@ singular_name=mlflow_experiment plural_name=experiments resource_type=MlflowExpe singular_name=mlflow_model plural_name=models resource_type=MlflowModel singular_name=model_serving_endpoint plural_name=model_serving_endpoints resource_type=ModelServingEndpoint singular_name=pipeline plural_name=pipelines resource_type=Pipeline +singular_name=postgres_snapshot_schedule plural_name=postgres_snapshot_schedules resource_type=PostgresSnapshotSchedule singular_name=quality_monitor plural_name=quality_monitors resource_type=QualityMonitor singular_name=registered_model plural_name=registered_models resource_type=RegisteredModel singular_name=schema plural_name=schemas resource_type=Schema From bb037743b31129047be7fb1e36170a0c1fa1eace Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Wed, 9 Sep 2026 07:41:24 +0000 Subject: [PATCH 18/22] Distinguish "not supported" from "not deployed" in bundle summary Resource types that never expose a workspace URL (the postgres_* resources, secret scopes, external locations, snapshots) rendered "URL: (not deployed)" in `bundle summary` even after a successful deploy, which was misleading. Add a type-level SupportsURL() to the ConfigResource interface (default true on BaseResource, overridden to false on the no-URL types) and render "(not supported)" for those, while keeping "(not deployed)" for URL-capable resources that are not deployed yet. Co-authored-by: Isaac --- .../bundles/summary-url-not-supported.md | 1 + .../deployment/bind/postgres_database/output.txt | 4 ++-- .../deployment/bind/postgres_role/output.txt | 4 ++-- .../bind/postgres_snapshot_schedule/output.txt | 4 ++-- .../resources/postgres_branches/basic/output.txt | 8 ++++---- .../resources/postgres_catalogs/basic/output.txt | 4 ++-- .../postgres_databases/basic/output.txt | 16 ++++++++-------- .../postgres_endpoints/basic/output.txt | 12 ++++++------ .../resources/postgres_projects/basic/output.txt | 4 ++-- .../resources/postgres_roles/basic/output.txt | 12 ++++++------ .../postgres_synced_tables/basic/output.txt | 4 ++-- bundle/config/resources.go | 5 +++++ bundle/config/resources/base.go | 6 ++++++ bundle/config/resources/external_location.go | 5 +++++ bundle/config/resources/postgres_branch.go | 5 +++++ bundle/config/resources/postgres_database.go | 5 +++++ bundle/config/resources/postgres_endpoint.go | 5 +++++ bundle/config/resources/postgres_project.go | 5 +++++ bundle/config/resources/postgres_role.go | 5 +++++ .../resources/postgres_snapshot_schedule.go | 5 +++++ bundle/config/resources/secret_scope.go | 5 +++++ bundle/config/resources/snapshot.go | 5 +++++ bundle/render/render_text_output.go | 16 +++++++++------- bundle/render/render_text_output_test.go | 10 ++++++++++ 24 files changed, 112 insertions(+), 43 deletions(-) create mode 100644 .nextchanges/bundles/summary-url-not-supported.md diff --git a/.nextchanges/bundles/summary-url-not-supported.md b/.nextchanges/bundles/summary-url-not-supported.md new file mode 100644 index 00000000000..80d189267b8 --- /dev/null +++ b/.nextchanges/bundles/summary-url-not-supported.md @@ -0,0 +1 @@ +* In `bundle summary`, resource types that never have a workspace URL now render `URL: (not supported)` instead of `URL: (not deployed)`. ([#6449](https://github.com/databricks/cli/pull/6449)) diff --git a/acceptance/bundle/deployment/bind/postgres_database/output.txt b/acceptance/bundle/deployment/bind/postgres_database/output.txt index 86bb47f3eff..a71b003a889 100644 --- a/acceptance/bundle/deployment/bind/postgres_database/output.txt +++ b/acceptance/bundle/deployment/bind/postgres_database/output.txt @@ -13,7 +13,7 @@ Resources: Postgres databases: database1: Name: - URL: (not deployed) + URL: (not supported) >>> [CLI] bundle deployment unbind database1 @@ -27,4 +27,4 @@ Resources: Postgres databases: database1: Name: - URL: (not deployed) + URL: (not supported) diff --git a/acceptance/bundle/deployment/bind/postgres_role/output.txt b/acceptance/bundle/deployment/bind/postgres_role/output.txt index ade277df2ae..fb8ab92a0cc 100644 --- a/acceptance/bundle/deployment/bind/postgres_role/output.txt +++ b/acceptance/bundle/deployment/bind/postgres_role/output.txt @@ -13,7 +13,7 @@ Resources: Postgres roles: role1: Name: - URL: (not deployed) + URL: (not supported) >>> [CLI] bundle deployment unbind role1 @@ -27,4 +27,4 @@ Resources: Postgres roles: role1: Name: - URL: (not deployed) + URL: (not supported) diff --git a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt index 8701019ab60..01098097e95 100644 --- a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt +++ b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt @@ -13,7 +13,7 @@ Resources: Postgres snapshot schedules: schedule1: Name: projects/test-project/branches/main/snapshot-schedule - URL: (not deployed) + URL: (not supported) >>> [CLI] bundle deployment unbind schedule1 @@ -27,4 +27,4 @@ Resources: Postgres snapshot schedules: schedule1: Name: - URL: (not deployed) + URL: (not supported) diff --git a/acceptance/bundle/resources/postgres_branches/basic/output.txt b/acceptance/bundle/resources/postgres_branches/basic/output.txt index e06e2d8413b..b4d86e3680e 100644 --- a/acceptance/bundle/resources/postgres_branches/basic/output.txt +++ b/acceptance/bundle/resources/postgres_branches/basic/output.txt @@ -18,11 +18,11 @@ Resources: Postgres branches: main: Name: - URL: (not deployed) + URL: (not supported) Postgres projects: my_project: Name: Test Project for Branch - URL: (not deployed) + URL: (not supported) >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-postgres-branch-[UNIQUE_NAME]/default/files... @@ -59,11 +59,11 @@ Resources: Postgres branches: main: Name: - URL: (not deployed) + URL: (not supported) Postgres projects: my_project: Name: Test Project for Branch - URL: (not deployed) + URL: (not supported) >>> print_requests.py --del-body project_id,branch_id,endpoint_id,database_id,role_id,catalog_id,synced_table_id --keep --get //postgres ^//workspace-files/ ^//workspace/ ^//telemetry-ext ^//operations/ diff --git a/acceptance/bundle/resources/postgres_catalogs/basic/output.txt b/acceptance/bundle/resources/postgres_catalogs/basic/output.txt index 3d0adb7dd20..b45d875d867 100644 --- a/acceptance/bundle/resources/postgres_catalogs/basic/output.txt +++ b/acceptance/bundle/resources/postgres_catalogs/basic/output.txt @@ -22,7 +22,7 @@ Resources: Postgres projects: my_project: Name: Test Project for Catalog - URL: (not deployed) + URL: (not supported) >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-postgres-catalog-[UNIQUE_NAME]/default/files... @@ -56,7 +56,7 @@ Resources: Postgres projects: my_project: Name: Test Project for Catalog - URL: (not deployed) + URL: (not supported) >>> print_requests.py --del-body project_id,branch_id,endpoint_id,database_id,role_id,catalog_id,synced_table_id --keep --get //postgres ^//workspace-files/ ^//workspace/ ^//telemetry-ext ^//operations/ diff --git a/acceptance/bundle/resources/postgres_databases/basic/output.txt b/acceptance/bundle/resources/postgres_databases/basic/output.txt index defd7cfdd1e..655c0d6979d 100644 --- a/acceptance/bundle/resources/postgres_databases/basic/output.txt +++ b/acceptance/bundle/resources/postgres_databases/basic/output.txt @@ -18,19 +18,19 @@ Resources: Postgres branches: main: Name: - URL: (not deployed) + URL: (not supported) Postgres databases: my_database: Name: - URL: (not deployed) + URL: (not supported) Postgres projects: my_project: Name: Test Project for Database - URL: (not deployed) + URL: (not supported) Postgres roles: owner: Name: - URL: (not deployed) + URL: (not supported) >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-postgres-database-[UNIQUE_NAME]/default/files... @@ -63,19 +63,19 @@ Resources: Postgres branches: main: Name: - URL: (not deployed) + URL: (not supported) Postgres databases: my_database: Name: - URL: (not deployed) + URL: (not supported) Postgres projects: my_project: Name: Test Project for Database - URL: (not deployed) + URL: (not supported) Postgres roles: owner: Name: - URL: (not deployed) + URL: (not supported) >>> print_requests.py --del-body project_id,branch_id,endpoint_id,database_id,role_id,catalog_id,synced_table_id --keep --get //postgres ^//workspace-files/ ^//workspace/ ^//telemetry-ext ^//operations/ diff --git a/acceptance/bundle/resources/postgres_endpoints/basic/output.txt b/acceptance/bundle/resources/postgres_endpoints/basic/output.txt index cef82784922..90f898d71dc 100644 --- a/acceptance/bundle/resources/postgres_endpoints/basic/output.txt +++ b/acceptance/bundle/resources/postgres_endpoints/basic/output.txt @@ -18,15 +18,15 @@ Resources: Postgres branches: main: Name: - URL: (not deployed) + URL: (not supported) Postgres endpoints: custom: Name: - URL: (not deployed) + URL: (not supported) Postgres projects: my_project: Name: Test Project for Endpoint - URL: (not deployed) + URL: (not supported) >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-postgres-endpoint-[UNIQUE_NAME]/default/files... @@ -61,15 +61,15 @@ Resources: Postgres branches: main: Name: - URL: (not deployed) + URL: (not supported) Postgres endpoints: custom: Name: - URL: (not deployed) + URL: (not supported) Postgres projects: my_project: Name: Test Project for Endpoint - URL: (not deployed) + URL: (not supported) >>> print_requests.py --del-body project_id,branch_id,endpoint_id,database_id,role_id,catalog_id,synced_table_id --keep --get //postgres ^//workspace-files/ ^//workspace/ ^//telemetry-ext ^//operations/ diff --git a/acceptance/bundle/resources/postgres_projects/basic/output.txt b/acceptance/bundle/resources/postgres_projects/basic/output.txt index 8290600440e..5a42cdb2be5 100644 --- a/acceptance/bundle/resources/postgres_projects/basic/output.txt +++ b/acceptance/bundle/resources/postgres_projects/basic/output.txt @@ -18,7 +18,7 @@ Resources: Postgres projects: my_project: Name: Test Postgres Project - URL: (not deployed) + URL: (not supported) >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-postgres-single-project-[UNIQUE_NAME]/default/files... @@ -59,7 +59,7 @@ Resources: Postgres projects: my_project: Name: Test Postgres Project - URL: (not deployed) + URL: (not supported) >>> print_requests.py --del-body project_id,branch_id,endpoint_id,database_id,role_id,catalog_id,synced_table_id --keep --get //postgres ^//workspace-files/ ^//workspace/ ^//telemetry-ext ^//operations/ diff --git a/acceptance/bundle/resources/postgres_roles/basic/output.txt b/acceptance/bundle/resources/postgres_roles/basic/output.txt index 7b292070dfb..60f8e57498e 100644 --- a/acceptance/bundle/resources/postgres_roles/basic/output.txt +++ b/acceptance/bundle/resources/postgres_roles/basic/output.txt @@ -18,15 +18,15 @@ Resources: Postgres branches: main: Name: - URL: (not deployed) + URL: (not supported) Postgres projects: my_project: Name: Test Project for Role - URL: (not deployed) + URL: (not supported) Postgres roles: my_role: Name: - URL: (not deployed) + URL: (not supported) >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-postgres-role-[UNIQUE_NAME]/default/files... @@ -64,15 +64,15 @@ Resources: Postgres branches: main: Name: - URL: (not deployed) + URL: (not supported) Postgres projects: my_project: Name: Test Project for Role - URL: (not deployed) + URL: (not supported) Postgres roles: my_role: Name: - URL: (not deployed) + URL: (not supported) >>> print_requests.py --del-body project_id,branch_id,endpoint_id,database_id,role_id,catalog_id,synced_table_id --keep --get //postgres ^//workspace-files/ ^//workspace/ ^//telemetry-ext ^//operations/ diff --git a/acceptance/bundle/resources/postgres_synced_tables/basic/output.txt b/acceptance/bundle/resources/postgres_synced_tables/basic/output.txt index e752198edcf..53e5fbc19a1 100644 --- a/acceptance/bundle/resources/postgres_synced_tables/basic/output.txt +++ b/acceptance/bundle/resources/postgres_synced_tables/basic/output.txt @@ -26,7 +26,7 @@ Resources: Postgres projects: my_project: Name: Test Project for Synced Table - URL: (not deployed) + URL: (not supported) Postgres synced tables: my_table: Name: ${resources.postgres_catalogs.my_catalog.catalog_id}.public.trips_synced @@ -65,7 +65,7 @@ Resources: Postgres projects: my_project: Name: Test Project for Synced Table - URL: (not deployed) + URL: (not supported) Postgres synced tables: my_table: Name: lakebase_test_[UNIQUE_NAME].public.trips_synced diff --git a/bundle/config/resources.go b/bundle/config/resources.go index ca92f8f3fe6..7c7a9a843bf 100644 --- a/bundle/config/resources.go +++ b/bundle/config/resources.go @@ -66,6 +66,11 @@ type ConfigResource interface { // GetURL returns the URL of the resource. GetURL() string + // SupportsURL reports whether this resource type can have a workspace URL. + // It distinguishes an empty GetURL() that means "not deployed yet" from one + // that means the type never has a URL. + SupportsURL() bool + // InitializeURL initializes the URL field of the resource. InitializeURL(baseURL url.URL) diff --git a/bundle/config/resources/base.go b/bundle/config/resources/base.go index ceeb1f0b869..613b80fe3fc 100644 --- a/bundle/config/resources/base.go +++ b/bundle/config/resources/base.go @@ -12,3 +12,9 @@ type BaseResource struct { func (b *BaseResource) GetLifecycle() LifecycleConfig { return b.Lifecycle } + +// SupportsURL reports whether this resource type can have a workspace URL. +// Types whose IDs don't map to a web UI page override this to return false. +func (b *BaseResource) SupportsURL() bool { + return true +} diff --git a/bundle/config/resources/external_location.go b/bundle/config/resources/external_location.go index cc413de84f3..9381e716075 100644 --- a/bundle/config/resources/external_location.go +++ b/bundle/config/resources/external_location.go @@ -58,6 +58,11 @@ func (e *ExternalLocation) GetURL() string { return "" } +func (e *ExternalLocation) SupportsURL() bool { + // External locations don't have a workspace URL + return false +} + func (e *ExternalLocation) GetName() string { return e.Name } diff --git a/bundle/config/resources/postgres_branch.go b/bundle/config/resources/postgres_branch.go index 2713c0cdd58..28f2c77bf37 100644 --- a/bundle/config/resources/postgres_branch.go +++ b/bundle/config/resources/postgres_branch.go @@ -87,6 +87,11 @@ func (b *PostgresBranch) GetURL() string { return "" } +func (b *PostgresBranch) SupportsURL() bool { + // The IDs in the API do not (yet) map to IDs in the web UI. + return false +} + func (b *PostgresBranch) InitializeURL(_ url.URL) { // The IDs in the API do not (yet) map to IDs in the web UI. } diff --git a/bundle/config/resources/postgres_database.go b/bundle/config/resources/postgres_database.go index ad16d720bb9..b511a55345d 100644 --- a/bundle/config/resources/postgres_database.go +++ b/bundle/config/resources/postgres_database.go @@ -79,6 +79,11 @@ func (d *PostgresDatabase) GetURL() string { return "" } +func (d *PostgresDatabase) SupportsURL() bool { + // The IDs in the API do not (yet) map to IDs in the web UI. + return false +} + func (d *PostgresDatabase) InitializeURL(_ url.URL) { // The IDs in the API do not (yet) map to IDs in the web UI. } diff --git a/bundle/config/resources/postgres_endpoint.go b/bundle/config/resources/postgres_endpoint.go index 1ae81fdf8ad..722967d81f2 100644 --- a/bundle/config/resources/postgres_endpoint.go +++ b/bundle/config/resources/postgres_endpoint.go @@ -75,6 +75,11 @@ func (e *PostgresEndpoint) GetURL() string { return "" } +func (e *PostgresEndpoint) SupportsURL() bool { + // The IDs in the API do not (yet) map to IDs in the web UI. + return false +} + func (e *PostgresEndpoint) InitializeURL(_ url.URL) { // The IDs in the API do not (yet) map to IDs in the web UI. } diff --git a/bundle/config/resources/postgres_project.go b/bundle/config/resources/postgres_project.go index 1f0165fd9b7..96379278877 100644 --- a/bundle/config/resources/postgres_project.go +++ b/bundle/config/resources/postgres_project.go @@ -80,6 +80,11 @@ func (p *PostgresProject) GetURL() string { return "" } +func (p *PostgresProject) SupportsURL() bool { + // The IDs in the API do not (yet) map to IDs in the web UI. + return false +} + func (p *PostgresProject) InitializeURL(_ url.URL) { // The IDs in the API do not (yet) map to IDs in the web UI. } diff --git a/bundle/config/resources/postgres_role.go b/bundle/config/resources/postgres_role.go index b45c6928557..bd427c48d35 100644 --- a/bundle/config/resources/postgres_role.go +++ b/bundle/config/resources/postgres_role.go @@ -80,6 +80,11 @@ func (r *PostgresRole) GetURL() string { return "" } +func (r *PostgresRole) SupportsURL() bool { + // The IDs in the API do not (yet) map to IDs in the web UI. + return false +} + func (r *PostgresRole) InitializeURL(_ url.URL) { // The IDs in the API do not (yet) map to IDs in the web UI. } diff --git a/bundle/config/resources/postgres_snapshot_schedule.go b/bundle/config/resources/postgres_snapshot_schedule.go index cc35d357417..120e3b75210 100644 --- a/bundle/config/resources/postgres_snapshot_schedule.go +++ b/bundle/config/resources/postgres_snapshot_schedule.go @@ -77,6 +77,11 @@ func (b *PostgresSnapshotSchedule) GetURL() string { return "" } +func (b *PostgresSnapshotSchedule) SupportsURL() bool { + // The IDs in the API do not (yet) map to IDs in the web UI. + return false +} + func (b *PostgresSnapshotSchedule) InitializeURL(_ url.URL) { // The IDs in the API do not (yet) map to IDs in the web UI. } diff --git a/bundle/config/resources/secret_scope.go b/bundle/config/resources/secret_scope.go index 30d0ebd901d..67849988ca9 100644 --- a/bundle/config/resources/secret_scope.go +++ b/bundle/config/resources/secret_scope.go @@ -109,6 +109,11 @@ func (s SecretScope) GetURL() string { return "" } +func (s SecretScope) SupportsURL() bool { + // Secret scopes do not have a URL + return false +} + func (s SecretScope) InitializeURL(_ url.URL) { // Secret scopes do not have a URL } diff --git a/bundle/config/resources/snapshot.go b/bundle/config/resources/snapshot.go index f323c93067b..5621cea1208 100644 --- a/bundle/config/resources/snapshot.go +++ b/bundle/config/resources/snapshot.go @@ -106,6 +106,11 @@ func (s *Snapshot) GetURL() string { return "" } +func (s *Snapshot) SupportsURL() bool { + // See GetURL: no browser URL is surfaced for the snapshot folder yet. + return false +} + func (s *Snapshot) InitializeURL(_ url.URL) { // See GetURL: no browser URL is surfaced for the snapshot folder yet. } diff --git a/bundle/render/render_text_output.go b/bundle/render/render_text_output.go index b1f0c6442d1..04f0deb53d7 100644 --- a/bundle/render/render_text_output.go +++ b/bundle/render/render_text_output.go @@ -40,7 +40,7 @@ const resourcesTemplate = `Resources: {{- range .Resources }} {{ .Key | bold }}: Name: {{ .Name }} - URL: {{ if .URL }}{{ .URL | cyan }}{{ else }}{{ "(not deployed)" | cyan }}{{ end }} + URL: {{ if .URL }}{{ .URL | cyan }}{{ else if .SupportsURL }}{{ "(not deployed)" | cyan }}{{ else }}{{ "(not supported)" | cyan }}{{ end }} {{- end }} {{- end }} ` @@ -51,9 +51,10 @@ type ResourceGroup struct { } type ResourceInfo struct { - Key string - Name string - URL string + Key string + Name string + URL string + SupportsURL bool } func pluralize(n int, singular, plural string) string { @@ -150,9 +151,10 @@ func RenderSummary(ctx context.Context, out io.Writer, b *bundle.Bundle) error { resources := make([]ResourceInfo, 0, len(group.Resources)) for key, resource := range group.Resources { resources = append(resources, ResourceInfo{ - Key: key, - Name: resource.GetName(), - URL: resource.GetURL(), + Key: key, + Name: resource.GetName(), + URL: resource.GetURL(), + SupportsURL: resource.SupportsURL(), }) } diff --git a/bundle/render/render_text_output_test.go b/bundle/render/render_text_output_test.go index b797b423ad5..c6e29126a47 100644 --- a/bundle/render/render_text_output_test.go +++ b/bundle/render/render_text_output_test.go @@ -335,6 +335,12 @@ func TestRenderSummary(t *testing.T) { }, }, }, + SecretScopes: map[string]*resources.SecretScope{ + // Secret scopes never have a URL, regardless of deployment. + "scope1": { + Name: "my_scope", + }, + }, }, }, } @@ -370,6 +376,10 @@ Resources: schema1: Name: schema URL: (not deployed) + Secret Scopes: + scope1: + Name: my_scope + URL: (not supported) ` assert.Equal(t, expectedSummary, writer.String()) } From f5840b8ec8fe55bdbc478c1fb63367e94033ae46 Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Wed, 9 Sep 2026 07:44:56 +0000 Subject: [PATCH 19/22] Reference PR #6583 in changelog fragment Co-authored-by: Isaac --- .nextchanges/bundles/summary-url-not-supported.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nextchanges/bundles/summary-url-not-supported.md b/.nextchanges/bundles/summary-url-not-supported.md index 80d189267b8..11c60f66d27 100644 --- a/.nextchanges/bundles/summary-url-not-supported.md +++ b/.nextchanges/bundles/summary-url-not-supported.md @@ -1 +1 @@ -* In `bundle summary`, resource types that never have a workspace URL now render `URL: (not supported)` instead of `URL: (not deployed)`. ([#6449](https://github.com/databricks/cli/pull/6449)) +* In `bundle summary`, resource types that never have a workspace URL now render `URL: (not supported)` instead of `URL: (not deployed)`. ([#6583](https://github.com/databricks/cli/pull/6583)) From 624287ff7fcdb360c3524304919d4aa83bf08caf Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Wed, 9 Sep 2026 10:58:40 +0000 Subject: [PATCH 20/22] Use SupportsURL() in bundle/pipelines open and pipelines deploy bundle open and pipelines open told the user a no-URL resource might just need deploying ("has it been deployed?"), and pipelines deploy printed "View your here:" with a blank URL for such resources. Guard all three on SupportsURL() so the message is honest and the blank line is skipped. Co-authored-by: Isaac --- acceptance/bundle/resources/postgres_roles/basic/output.txt | 3 +++ acceptance/bundle/resources/postgres_roles/basic/script | 4 ++++ cmd/bundle/open.go | 3 +++ cmd/pipelines/deploy.go | 5 +++++ cmd/pipelines/open.go | 3 +++ 5 files changed, 18 insertions(+) diff --git a/acceptance/bundle/resources/postgres_roles/basic/output.txt b/acceptance/bundle/resources/postgres_roles/basic/output.txt index 60f8e57498e..3edfde9d20d 100644 --- a/acceptance/bundle/resources/postgres_roles/basic/output.txt +++ b/acceptance/bundle/resources/postgres_roles/basic/output.txt @@ -54,6 +54,9 @@ Resources: 3 created, 0 changed, 0 deleted, 0 unchanged } } +>>> musterr [CLI] bundle open my_role +Error: this resource type does not have a URL + >>> [CLI] bundle summary Name: deploy-postgres-role-[UNIQUE_NAME] Target: default diff --git a/acceptance/bundle/resources/postgres_roles/basic/script b/acceptance/bundle/resources/postgres_roles/basic/script index d5e3f421cd7..bd91b06dd39 100644 --- a/acceptance/bundle/resources/postgres_roles/basic/script +++ b/acceptance/bundle/resources/postgres_roles/basic/script @@ -19,6 +19,10 @@ branch_name="${project_name}/branches/main" role_name="${branch_name}/roles/test-role" trace $CLI postgres get-role "${role_name}" | role_fields +# Postgres roles have no workspace URL, so opening one reports that rather than +# suggesting a deploy. +trace musterr $CLI bundle open my_role + trace $CLI bundle summary # Filter requests to only show postgres operations (exclude workspace, telemetry, and operation polling) diff --git a/cmd/bundle/open.go b/cmd/bundle/open.go index d357b4f39e1..ccb3cd201a0 100644 --- a/cmd/bundle/open.go +++ b/cmd/bundle/open.go @@ -88,6 +88,9 @@ Use after deployment to quickly navigate to your resources in the workspace.`, } // Confirm that the resource has a URL. + if !ref.Resource.SupportsURL() { + return errors.New("this resource type does not have a URL") + } url := ref.Resource.GetURL() if url == "" { return errors.New("resource does not have a URL associated with it (has it been deployed?)") diff --git a/cmd/pipelines/deploy.go b/cmd/pipelines/deploy.go index 53af02c55a4..dc28f947aae 100644 --- a/cmd/pipelines/deploy.go +++ b/cmd/pipelines/deploy.go @@ -74,6 +74,11 @@ func deployCommand() *cobra.Command { for _, group := range b.Config.Resources.AllResources() { for _, resourceKey := range slices.Sorted(maps.Keys(group.Resources)) { resource := group.Resources[resourceKey] + // Skip resource types that never have a URL; otherwise we'd print + // "View your here:" with a blank URL. + if !resource.SupportsURL() { + continue + } cmdio.LogString(ctx, fmt.Sprintf("View your %s %s here: %s", resource.ResourceDescription().SingularName, resourceKey, resource.GetURL())) } } diff --git a/cmd/pipelines/open.go b/cmd/pipelines/open.go index 6a8419703be..f75bb899777 100644 --- a/cmd/pipelines/open.go +++ b/cmd/pipelines/open.go @@ -72,6 +72,9 @@ If there is only one pipeline in the project, KEY is optional and the pipeline w } // Confirm that the resource has a URL. + if !ref.Resource.SupportsURL() { + return errors.New("this resource type does not have a URL") + } url := ref.Resource.GetURL() if url == "" { return errors.New("pipeline does not have a URL associated with it (has it been deployed?)") From 4d46bd6c316185afd81e4fe569b1cc33cfa339c1 Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Wed, 9 Sep 2026 12:11:00 +0000 Subject: [PATCH 21/22] Fold SupportsURL into GetURL() (string, bool) Address review: rather than a separate SupportsURL() method, GetURL now returns (url, supported), following the (value, ok) idiom (cf. context.Context.Deadline). The default lives on BaseResource like GetLifecycle, so the 27 trivial 'return X.URL' overrides are dropped and only the 9 no-URL types override to return ("", false). Also consolidate the changelog into a single generic entry covering all affected commands. Co-authored-by: Isaac --- .nextchanges/bundles/summary-url-not-supported.md | 1 - .nextchanges/bundles/url-not-supported.md | 1 + bundle/config/mutator/initialize_urls_test.go | 3 ++- bundle/config/resources.go | 11 ++++------- bundle/config/resources/alerts.go | 4 ---- bundle/config/resources/apps.go | 4 ---- bundle/config/resources/base.go | 8 ++++---- bundle/config/resources/catalog.go | 4 ---- bundle/config/resources/cluster_policy.go | 4 ---- bundle/config/resources/clusters.go | 4 ---- bundle/config/resources/dashboard.go | 4 ---- bundle/config/resources/database_catalog.go | 4 ---- bundle/config/resources/database_instance.go | 4 ---- bundle/config/resources/external_location.go | 9 ++------- bundle/config/resources/genie_space.go | 4 ---- bundle/config/resources/instance_pools.go | 4 ---- bundle/config/resources/job.go | 4 ---- bundle/config/resources/job_run.go | 4 ---- bundle/config/resources/mlflow_experiment.go | 4 ---- bundle/config/resources/mlflow_model.go | 4 ---- bundle/config/resources/model_serving_endpoint.go | 4 ---- bundle/config/resources/pipeline.go | 4 ---- bundle/config/resources/postgres_branch.go | 9 ++------- bundle/config/resources/postgres_catalog.go | 4 ---- bundle/config/resources/postgres_database.go | 9 ++------- bundle/config/resources/postgres_endpoint.go | 9 ++------- bundle/config/resources/postgres_project.go | 9 ++------- bundle/config/resources/postgres_role.go | 9 ++------- bundle/config/resources/postgres_snapshot_schedule.go | 9 ++------- bundle/config/resources/postgres_synced_table.go | 4 ---- bundle/config/resources/quality_monitor.go | 4 ---- bundle/config/resources/registered_model.go | 4 ---- bundle/config/resources/schema.go | 4 ---- bundle/config/resources/secret.go | 4 ---- bundle/config/resources/secret_scope.go | 9 ++------- bundle/config/resources/snapshot.go | 9 ++------- bundle/config/resources/sql_warehouses.go | 4 ---- bundle/config/resources/synced_database_table.go | 4 ---- bundle/config/resources/vector_search_endpoint.go | 4 ---- bundle/config/resources/vector_search_index.go | 4 ---- bundle/config/resources/volume.go | 4 ---- bundle/render/render_text_output.go | 5 +++-- cmd/bundle/open.go | 4 ++-- cmd/pipelines/deploy.go | 5 +++-- cmd/pipelines/open.go | 4 ++-- 45 files changed, 39 insertions(+), 192 deletions(-) delete mode 100644 .nextchanges/bundles/summary-url-not-supported.md create mode 100644 .nextchanges/bundles/url-not-supported.md diff --git a/.nextchanges/bundles/summary-url-not-supported.md b/.nextchanges/bundles/summary-url-not-supported.md deleted file mode 100644 index 11c60f66d27..00000000000 --- a/.nextchanges/bundles/summary-url-not-supported.md +++ /dev/null @@ -1 +0,0 @@ -* In `bundle summary`, resource types that never have a workspace URL now render `URL: (not supported)` instead of `URL: (not deployed)`. ([#6583](https://github.com/databricks/cli/pull/6583)) diff --git a/.nextchanges/bundles/url-not-supported.md b/.nextchanges/bundles/url-not-supported.md new file mode 100644 index 00000000000..86cc00a1dd9 --- /dev/null +++ b/.nextchanges/bundles/url-not-supported.md @@ -0,0 +1 @@ +* Resources that do not support a workspace URL now report that in CLI commands, instead of misleading the user into thinking the resource is not deployed. ([#6583](https://github.com/databricks/cli/pull/6583)) diff --git a/bundle/config/mutator/initialize_urls_test.go b/bundle/config/mutator/initialize_urls_test.go index b3e10660b31..980c4d88514 100644 --- a/bundle/config/mutator/initialize_urls_test.go +++ b/bundle/config/mutator/initialize_urls_test.go @@ -124,7 +124,8 @@ func TestInitializeURLs(t *testing.T) { for _, group := range b.Config.Resources.AllResources() { for key, r := range group.Resources { - require.Equal(t, expectedURLs[key], r.GetURL(), "Unexpected URL for "+key) + url, _ := r.GetURL() + require.Equal(t, expectedURLs[key], url, "Unexpected URL for "+key) } } } diff --git a/bundle/config/resources.go b/bundle/config/resources.go index 7c7a9a843bf..d62b89d9384 100644 --- a/bundle/config/resources.go +++ b/bundle/config/resources.go @@ -63,13 +63,10 @@ type ConfigResource interface { // GetName returns the in-product name of the resource. GetName() string - // GetURL returns the URL of the resource. - GetURL() string - - // SupportsURL reports whether this resource type can have a workspace URL. - // It distinguishes an empty GetURL() that means "not deployed yet" from one - // that means the type never has a URL. - SupportsURL() bool + // GetURL returns the resource's workspace URL and whether this resource type + // has one at all. A supported type that is not deployed yet returns ("", true); + // a type that never has a URL returns ("", false). + GetURL() (string, bool) // InitializeURL initializes the URL field of the resource. InitializeURL(baseURL url.URL) diff --git a/bundle/config/resources/alerts.go b/bundle/config/resources/alerts.go index 628302c4e3b..cf3119a6f9c 100644 --- a/bundle/config/resources/alerts.go +++ b/bundle/config/resources/alerts.go @@ -59,7 +59,3 @@ func (a *Alert) InitializeURL(baseURL url.URL) { func (a *Alert) GetName() string { return a.DisplayName } - -func (a *Alert) GetURL() string { - return a.URL -} diff --git a/bundle/config/resources/apps.go b/bundle/config/resources/apps.go index a26670c4897..f1d62bcc893 100644 --- a/bundle/config/resources/apps.go +++ b/bundle/config/resources/apps.go @@ -102,7 +102,3 @@ func (a *App) GetName() string { } return a.Name } - -func (a *App) GetURL() string { - return a.URL -} diff --git a/bundle/config/resources/base.go b/bundle/config/resources/base.go index 613b80fe3fc..6a27d2b6e47 100644 --- a/bundle/config/resources/base.go +++ b/bundle/config/resources/base.go @@ -13,8 +13,8 @@ func (b *BaseResource) GetLifecycle() LifecycleConfig { return b.Lifecycle } -// SupportsURL reports whether this resource type can have a workspace URL. -// Types whose IDs don't map to a web UI page override this to return false. -func (b *BaseResource) SupportsURL() bool { - return true +// GetURL returns the resource's workspace URL and true. Resource types whose +// IDs don't map to a web UI page override this to return ("", false). +func (b *BaseResource) GetURL() (string, bool) { + return b.URL, true } diff --git a/bundle/config/resources/catalog.go b/bundle/config/resources/catalog.go index 0bc28f1d99f..8c5f6dcb853 100644 --- a/bundle/config/resources/catalog.go +++ b/bundle/config/resources/catalog.go @@ -51,10 +51,6 @@ func (c *Catalog) InitializeURL(baseURL url.URL) { c.URL = workspaceurls.ResourceURL(baseURL, "catalogs", c.ID) } -func (c *Catalog) GetURL() string { - return c.URL -} - func (c *Catalog) GetName() string { return c.Name } diff --git a/bundle/config/resources/cluster_policy.go b/bundle/config/resources/cluster_policy.go index b0b07ff5fb9..f8f4a0f7170 100644 --- a/bundle/config/resources/cluster_policy.go +++ b/bundle/config/resources/cluster_policy.go @@ -63,7 +63,3 @@ func (s *ClusterPolicy) InitializeURL(baseURL url.URL) { func (s *ClusterPolicy) GetName() string { return s.Name } - -func (s *ClusterPolicy) GetURL() string { - return s.URL -} diff --git a/bundle/config/resources/clusters.go b/bundle/config/resources/clusters.go index 235ea6eee1a..9de7b62c526 100644 --- a/bundle/config/resources/clusters.go +++ b/bundle/config/resources/clusters.go @@ -65,7 +65,3 @@ func (s *Cluster) InitializeURL(baseURL url.URL) { func (s *Cluster) GetName() string { return s.ClusterName } - -func (s *Cluster) GetURL() string { - return s.URL -} diff --git a/bundle/config/resources/dashboard.go b/bundle/config/resources/dashboard.go index 8bd5603f150..692fc62b61b 100644 --- a/bundle/config/resources/dashboard.go +++ b/bundle/config/resources/dashboard.go @@ -128,7 +128,3 @@ func (r *Dashboard) InitializeURL(baseURL url.URL) { func (r *Dashboard) GetName() string { return r.DisplayName } - -func (r *Dashboard) GetURL() string { - return r.URL -} diff --git a/bundle/config/resources/database_catalog.go b/bundle/config/resources/database_catalog.go index ce525be2e9e..ddae1ea1892 100644 --- a/bundle/config/resources/database_catalog.go +++ b/bundle/config/resources/database_catalog.go @@ -47,10 +47,6 @@ func (d *DatabaseCatalog) GetName() string { return d.Name } -func (d *DatabaseCatalog) GetURL() string { - return d.URL -} - func (d *DatabaseCatalog) InitializeURL(baseURL url.URL) { if d.Name == "" { return diff --git a/bundle/config/resources/database_instance.go b/bundle/config/resources/database_instance.go index f219467d2ab..661ced94996 100644 --- a/bundle/config/resources/database_instance.go +++ b/bundle/config/resources/database_instance.go @@ -49,10 +49,6 @@ func (d *DatabaseInstance) GetName() string { return d.Name } -func (d *DatabaseInstance) GetURL() string { - return d.URL -} - func (d *DatabaseInstance) InitializeURL(baseURL url.URL) { if d.ModifiedStatus == ModifiedStatusCreated { return diff --git a/bundle/config/resources/external_location.go b/bundle/config/resources/external_location.go index 9381e716075..5d9a52a1b75 100644 --- a/bundle/config/resources/external_location.go +++ b/bundle/config/resources/external_location.go @@ -53,14 +53,9 @@ func (e *ExternalLocation) InitializeURL(baseURL url.URL) { // The Url field is for the storage path (s3://...), not a workspace URL } -func (e *ExternalLocation) GetURL() string { - // Return empty as external locations don't have a workspace URL - return "" -} - -func (e *ExternalLocation) SupportsURL() bool { +func (e *ExternalLocation) GetURL() (string, bool) { // External locations don't have a workspace URL - return false + return "", false } func (e *ExternalLocation) GetName() string { diff --git a/bundle/config/resources/genie_space.go b/bundle/config/resources/genie_space.go index 18e2fa1d8c7..19ce4702892 100644 --- a/bundle/config/resources/genie_space.go +++ b/bundle/config/resources/genie_space.go @@ -104,7 +104,3 @@ func (r *GenieSpace) InitializeURL(baseURL url.URL) { func (r *GenieSpace) GetName() string { return r.Title } - -func (r *GenieSpace) GetURL() string { - return r.URL -} diff --git a/bundle/config/resources/instance_pools.go b/bundle/config/resources/instance_pools.go index 31c4ee45a69..09179f509a0 100644 --- a/bundle/config/resources/instance_pools.go +++ b/bundle/config/resources/instance_pools.go @@ -53,7 +53,3 @@ func (s *InstancePool) InitializeURL(baseURL url.URL) { func (s *InstancePool) GetName() string { return s.InstancePoolName } - -func (s *InstancePool) GetURL() string { - return s.URL -} diff --git a/bundle/config/resources/job.go b/bundle/config/resources/job.go index 646750ef859..5f0eda4a172 100644 --- a/bundle/config/resources/job.go +++ b/bundle/config/resources/job.go @@ -61,7 +61,3 @@ func (j *Job) InitializeURL(baseURL url.URL) { func (j *Job) GetName() string { return j.Name } - -func (j *Job) GetURL() string { - return j.URL -} diff --git a/bundle/config/resources/job_run.go b/bundle/config/resources/job_run.go index 56f3c39a356..167530465e8 100644 --- a/bundle/config/resources/job_run.go +++ b/bundle/config/resources/job_run.go @@ -84,10 +84,6 @@ func (r *JobRun) GetName() string { return "" } -func (r *JobRun) GetURL() string { - return r.URL -} - // InitializeURL sets the run's workspace URL. The job id comes from RunNow.JobId // when resolved (deploy) or ResolvedJobID from state (read-only commands); if // either id is missing we skip rather than emit a broken jobs/0 URL. diff --git a/bundle/config/resources/mlflow_experiment.go b/bundle/config/resources/mlflow_experiment.go index c7db059bc8b..55b1bde4f23 100644 --- a/bundle/config/resources/mlflow_experiment.go +++ b/bundle/config/resources/mlflow_experiment.go @@ -56,7 +56,3 @@ func (s *MlflowExperiment) InitializeURL(baseURL url.URL) { func (s *MlflowExperiment) GetName() string { return s.Name } - -func (s *MlflowExperiment) GetURL() string { - return s.URL -} diff --git a/bundle/config/resources/mlflow_model.go b/bundle/config/resources/mlflow_model.go index c153e2d95e9..eb2adf01583 100644 --- a/bundle/config/resources/mlflow_model.go +++ b/bundle/config/resources/mlflow_model.go @@ -56,7 +56,3 @@ func (s *MlflowModel) InitializeURL(baseURL url.URL) { func (s *MlflowModel) GetName() string { return s.Name } - -func (s *MlflowModel) GetURL() string { - return s.URL -} diff --git a/bundle/config/resources/model_serving_endpoint.go b/bundle/config/resources/model_serving_endpoint.go index 5a917c2e268..e23d3d7b682 100644 --- a/bundle/config/resources/model_serving_endpoint.go +++ b/bundle/config/resources/model_serving_endpoint.go @@ -61,7 +61,3 @@ func (s *ModelServingEndpoint) InitializeURL(baseURL url.URL) { func (s *ModelServingEndpoint) GetName() string { return s.Name } - -func (s *ModelServingEndpoint) GetURL() string { - return s.URL -} diff --git a/bundle/config/resources/pipeline.go b/bundle/config/resources/pipeline.go index 7c205f7dc14..80c72e62fc9 100644 --- a/bundle/config/resources/pipeline.go +++ b/bundle/config/resources/pipeline.go @@ -61,7 +61,3 @@ func (p *Pipeline) InitializeURL(baseURL url.URL) { func (p *Pipeline) GetName() string { return p.Name } - -func (p *Pipeline) GetURL() string { - return p.URL -} diff --git a/bundle/config/resources/postgres_branch.go b/bundle/config/resources/postgres_branch.go index 28f2c77bf37..9d77863792a 100644 --- a/bundle/config/resources/postgres_branch.go +++ b/bundle/config/resources/postgres_branch.go @@ -82,14 +82,9 @@ func (b *PostgresBranch) GetName() string { return "" } -func (b *PostgresBranch) GetURL() string { +func (b *PostgresBranch) GetURL() (string, bool) { // The IDs in the API do not (yet) map to IDs in the web UI. - return "" -} - -func (b *PostgresBranch) SupportsURL() bool { - // The IDs in the API do not (yet) map to IDs in the web UI. - return false + return "", false } func (b *PostgresBranch) InitializeURL(_ url.URL) { diff --git a/bundle/config/resources/postgres_catalog.go b/bundle/config/resources/postgres_catalog.go index d1c788aece6..65c0f97112c 100644 --- a/bundle/config/resources/postgres_catalog.go +++ b/bundle/config/resources/postgres_catalog.go @@ -62,10 +62,6 @@ func (c *PostgresCatalog) GetName() string { return c.CatalogId } -func (c *PostgresCatalog) GetURL() string { - return c.URL -} - func (c *PostgresCatalog) InitializeURL(baseURL url.URL) { if c.CatalogId == "" { return diff --git a/bundle/config/resources/postgres_database.go b/bundle/config/resources/postgres_database.go index b511a55345d..3bebe476c2d 100644 --- a/bundle/config/resources/postgres_database.go +++ b/bundle/config/resources/postgres_database.go @@ -74,14 +74,9 @@ func (d *PostgresDatabase) GetName() string { return "" } -func (d *PostgresDatabase) GetURL() string { +func (d *PostgresDatabase) GetURL() (string, bool) { // The IDs in the API do not (yet) map to IDs in the web UI. - return "" -} - -func (d *PostgresDatabase) SupportsURL() bool { - // The IDs in the API do not (yet) map to IDs in the web UI. - return false + return "", false } func (d *PostgresDatabase) InitializeURL(_ url.URL) { diff --git a/bundle/config/resources/postgres_endpoint.go b/bundle/config/resources/postgres_endpoint.go index 722967d81f2..0bdfc25306c 100644 --- a/bundle/config/resources/postgres_endpoint.go +++ b/bundle/config/resources/postgres_endpoint.go @@ -70,14 +70,9 @@ func (e *PostgresEndpoint) GetName() string { return "" } -func (e *PostgresEndpoint) GetURL() string { +func (e *PostgresEndpoint) GetURL() (string, bool) { // The IDs in the API do not (yet) map to IDs in the web UI. - return "" -} - -func (e *PostgresEndpoint) SupportsURL() bool { - // The IDs in the API do not (yet) map to IDs in the web UI. - return false + return "", false } func (e *PostgresEndpoint) InitializeURL(_ url.URL) { diff --git a/bundle/config/resources/postgres_project.go b/bundle/config/resources/postgres_project.go index 96379278877..4b021737c97 100644 --- a/bundle/config/resources/postgres_project.go +++ b/bundle/config/resources/postgres_project.go @@ -75,14 +75,9 @@ func (p *PostgresProject) GetName() string { return p.DisplayName } -func (p *PostgresProject) GetURL() string { +func (p *PostgresProject) GetURL() (string, bool) { // The IDs in the API do not (yet) map to IDs in the web UI. - return "" -} - -func (p *PostgresProject) SupportsURL() bool { - // The IDs in the API do not (yet) map to IDs in the web UI. - return false + return "", false } func (p *PostgresProject) InitializeURL(_ url.URL) { diff --git a/bundle/config/resources/postgres_role.go b/bundle/config/resources/postgres_role.go index bd427c48d35..53dcc02d47c 100644 --- a/bundle/config/resources/postgres_role.go +++ b/bundle/config/resources/postgres_role.go @@ -75,14 +75,9 @@ func (r *PostgresRole) GetName() string { return "" } -func (r *PostgresRole) GetURL() string { +func (r *PostgresRole) GetURL() (string, bool) { // The IDs in the API do not (yet) map to IDs in the web UI. - return "" -} - -func (r *PostgresRole) SupportsURL() bool { - // The IDs in the API do not (yet) map to IDs in the web UI. - return false + return "", false } func (r *PostgresRole) InitializeURL(_ url.URL) { diff --git a/bundle/config/resources/postgres_snapshot_schedule.go b/bundle/config/resources/postgres_snapshot_schedule.go index 120e3b75210..a13b78cef82 100644 --- a/bundle/config/resources/postgres_snapshot_schedule.go +++ b/bundle/config/resources/postgres_snapshot_schedule.go @@ -72,14 +72,9 @@ func (b *PostgresSnapshotSchedule) GetName() string { return b.ID } -func (b *PostgresSnapshotSchedule) GetURL() string { +func (b *PostgresSnapshotSchedule) GetURL() (string, bool) { // The IDs in the API do not (yet) map to IDs in the web UI. - return "" -} - -func (b *PostgresSnapshotSchedule) SupportsURL() bool { - // The IDs in the API do not (yet) map to IDs in the web UI. - return false + return "", false } func (b *PostgresSnapshotSchedule) InitializeURL(_ url.URL) { diff --git a/bundle/config/resources/postgres_synced_table.go b/bundle/config/resources/postgres_synced_table.go index e92f19c2ab4..d377e6cc1cd 100644 --- a/bundle/config/resources/postgres_synced_table.go +++ b/bundle/config/resources/postgres_synced_table.go @@ -72,10 +72,6 @@ func (s *PostgresSyncedTable) GetName() string { return s.SyncedTableId } -func (s *PostgresSyncedTable) GetURL() string { - return s.URL -} - func (s *PostgresSyncedTable) InitializeURL(baseURL url.URL) { // UC explore expects /{catalog}/{schema}/{table}, so bail if the name isn't // a fully resolved three-part identifier; an unresolved ${...} reference diff --git a/bundle/config/resources/quality_monitor.go b/bundle/config/resources/quality_monitor.go index e3f39c7c69c..dd6143aa4a4 100644 --- a/bundle/config/resources/quality_monitor.go +++ b/bundle/config/resources/quality_monitor.go @@ -60,7 +60,3 @@ func (s *QualityMonitor) InitializeURL(baseURL url.URL) { func (s *QualityMonitor) GetName() string { return s.TableName } - -func (s *QualityMonitor) GetURL() string { - return s.URL -} diff --git a/bundle/config/resources/registered_model.go b/bundle/config/resources/registered_model.go index 87b0f0748c1..85288bee629 100644 --- a/bundle/config/resources/registered_model.go +++ b/bundle/config/resources/registered_model.go @@ -60,7 +60,3 @@ func (s *RegisteredModel) InitializeURL(baseURL url.URL) { func (s *RegisteredModel) GetName() string { return s.Name } - -func (s *RegisteredModel) GetURL() string { - return s.URL -} diff --git a/bundle/config/resources/schema.go b/bundle/config/resources/schema.go index f40a94c3529..71f2b13f887 100644 --- a/bundle/config/resources/schema.go +++ b/bundle/config/resources/schema.go @@ -53,10 +53,6 @@ func (s *Schema) InitializeURL(baseURL url.URL) { s.URL = workspaceurls.ResourceURL(baseURL, "schemas", s.ID) } -func (s *Schema) GetURL() string { - return s.URL -} - func (s *Schema) GetName() string { return s.Name } diff --git a/bundle/config/resources/secret.go b/bundle/config/resources/secret.go index d7fe4ed1a71..5730fcac92f 100644 --- a/bundle/config/resources/secret.go +++ b/bundle/config/resources/secret.go @@ -63,10 +63,6 @@ func (s *Secret) InitializeURL(baseURL url.URL) { s.URL = workspaceurls.ResourceURL(baseURL, "secrets", s.ID) } -func (s *Secret) GetURL() string { - return s.URL -} - func (s *Secret) GetName() string { if s.ID != "" { return s.ID diff --git a/bundle/config/resources/secret_scope.go b/bundle/config/resources/secret_scope.go index 67849988ca9..73647d2802a 100644 --- a/bundle/config/resources/secret_scope.go +++ b/bundle/config/resources/secret_scope.go @@ -104,14 +104,9 @@ func (s SecretScope) GetName() string { return s.Name } -func (s SecretScope) GetURL() string { +func (s SecretScope) GetURL() (string, bool) { // Secret scopes do not have a URL - return "" -} - -func (s SecretScope) SupportsURL() bool { - // Secret scopes do not have a URL - return false + return "", false } func (s SecretScope) InitializeURL(_ url.URL) { diff --git a/bundle/config/resources/snapshot.go b/bundle/config/resources/snapshot.go index 5621cea1208..95d98c89271 100644 --- a/bundle/config/resources/snapshot.go +++ b/bundle/config/resources/snapshot.go @@ -98,17 +98,12 @@ func (s *Snapshot) GetName() string { return s.RelativePath() } -func (s *Snapshot) GetURL() string { +func (s *Snapshot) GetURL() (string, bool) { // A snapshot is a workspace folder owned by the project's service principal, so // a browser URL is constructible from its path. We don't surface one yet: // workspaceurls has no folder-path helper, and the path is only known during // deploy (its content hash is derived from the zip staged by the deploy pipeline). - return "" -} - -func (s *Snapshot) SupportsURL() bool { - // See GetURL: no browser URL is surfaced for the snapshot folder yet. - return false + return "", false } func (s *Snapshot) InitializeURL(_ url.URL) { diff --git a/bundle/config/resources/sql_warehouses.go b/bundle/config/resources/sql_warehouses.go index 56653d27c99..a279c0054cf 100644 --- a/bundle/config/resources/sql_warehouses.go +++ b/bundle/config/resources/sql_warehouses.go @@ -65,7 +65,3 @@ func (sw *SqlWarehouse) InitializeURL(baseURL url.URL) { func (sw *SqlWarehouse) GetName() string { return sw.Name } - -func (sw *SqlWarehouse) GetURL() string { - return sw.URL -} diff --git a/bundle/config/resources/synced_database_table.go b/bundle/config/resources/synced_database_table.go index 4f6bb301463..18dcde00a74 100644 --- a/bundle/config/resources/synced_database_table.go +++ b/bundle/config/resources/synced_database_table.go @@ -47,10 +47,6 @@ func (s *SyncedDatabaseTable) GetName() string { return s.Name } -func (s *SyncedDatabaseTable) GetURL() string { - return s.URL -} - func (s *SyncedDatabaseTable) InitializeURL(baseURL url.URL) { if s.Name == "" { return diff --git a/bundle/config/resources/vector_search_endpoint.go b/bundle/config/resources/vector_search_endpoint.go index 13f8d790a53..dffb75e95f7 100644 --- a/bundle/config/resources/vector_search_endpoint.go +++ b/bundle/config/resources/vector_search_endpoint.go @@ -58,7 +58,3 @@ func (e *VectorSearchEndpoint) InitializeURL(baseURL url.URL) { func (e *VectorSearchEndpoint) GetName() string { return e.Name } - -func (e *VectorSearchEndpoint) GetURL() string { - return e.URL -} diff --git a/bundle/config/resources/vector_search_index.go b/bundle/config/resources/vector_search_index.go index c2990efac8d..4f82d51e2f8 100644 --- a/bundle/config/resources/vector_search_index.go +++ b/bundle/config/resources/vector_search_index.go @@ -64,7 +64,3 @@ func (e *VectorSearchIndex) InitializeURL(baseURL url.URL) { func (e *VectorSearchIndex) GetName() string { return e.Name } - -func (e *VectorSearchIndex) GetURL() string { - return e.URL -} diff --git a/bundle/config/resources/volume.go b/bundle/config/resources/volume.go index 139ca5e4785..8377414b588 100644 --- a/bundle/config/resources/volume.go +++ b/bundle/config/resources/volume.go @@ -66,10 +66,6 @@ func (v *Volume) InitializeURL(baseURL url.URL) { v.URL = workspaceurls.ResourceURL(baseURL, "volumes", v.ID) } -func (v *Volume) GetURL() string { - return v.URL -} - func (v *Volume) GetName() string { return v.Name } diff --git a/bundle/render/render_text_output.go b/bundle/render/render_text_output.go index 04f0deb53d7..767e5853d8d 100644 --- a/bundle/render/render_text_output.go +++ b/bundle/render/render_text_output.go @@ -150,11 +150,12 @@ func RenderSummary(ctx context.Context, out io.Writer, b *bundle.Bundle) error { for _, group := range b.Config.Resources.AllResources() { resources := make([]ResourceInfo, 0, len(group.Resources)) for key, resource := range group.Resources { + url, supportsURL := resource.GetURL() resources = append(resources, ResourceInfo{ Key: key, Name: resource.GetName(), - URL: resource.GetURL(), - SupportsURL: resource.SupportsURL(), + URL: url, + SupportsURL: supportsURL, }) } diff --git a/cmd/bundle/open.go b/cmd/bundle/open.go index ccb3cd201a0..5926b1419f8 100644 --- a/cmd/bundle/open.go +++ b/cmd/bundle/open.go @@ -88,10 +88,10 @@ Use after deployment to quickly navigate to your resources in the workspace.`, } // Confirm that the resource has a URL. - if !ref.Resource.SupportsURL() { + url, supported := ref.Resource.GetURL() + if !supported { return errors.New("this resource type does not have a URL") } - url := ref.Resource.GetURL() if url == "" { return errors.New("resource does not have a URL associated with it (has it been deployed?)") } diff --git a/cmd/pipelines/deploy.go b/cmd/pipelines/deploy.go index dc28f947aae..7275eb246b5 100644 --- a/cmd/pipelines/deploy.go +++ b/cmd/pipelines/deploy.go @@ -76,10 +76,11 @@ func deployCommand() *cobra.Command { resource := group.Resources[resourceKey] // Skip resource types that never have a URL; otherwise we'd print // "View your here:" with a blank URL. - if !resource.SupportsURL() { + url, supported := resource.GetURL() + if !supported { continue } - cmdio.LogString(ctx, fmt.Sprintf("View your %s %s here: %s", resource.ResourceDescription().SingularName, resourceKey, resource.GetURL())) + cmdio.LogString(ctx, fmt.Sprintf("View your %s %s here: %s", resource.ResourceDescription().SingularName, resourceKey, url)) } } diff --git a/cmd/pipelines/open.go b/cmd/pipelines/open.go index f75bb899777..8c0e88510e7 100644 --- a/cmd/pipelines/open.go +++ b/cmd/pipelines/open.go @@ -72,10 +72,10 @@ If there is only one pipeline in the project, KEY is optional and the pipeline w } // Confirm that the resource has a URL. - if !ref.Resource.SupportsURL() { + url, supported := ref.Resource.GetURL() + if !supported { return errors.New("this resource type does not have a URL") } - url := ref.Resource.GetURL() if url == "" { return errors.New("pipeline does not have a URL associated with it (has it been deployed?)") } From feb4032325b5fc7de39d04fdbdafbde0eff950d1 Mon Sep 17 00:00:00 2001 From: Jan Rose Date: Wed, 9 Sep 2026 12:20:41 +0000 Subject: [PATCH 22/22] Omit the URL row in bundle summary for resource types without a URL Per review: instead of printing a placeholder like "(not supported)" (which reads ambiguously), the summary template now skips the URL line entirely when GetURL reports the type has no URL. URL-capable resources are unchanged, including the "(not deployed)" case. Co-authored-by: Isaac --- .nextchanges/bundles/url-not-supported.md | 2 +- .../bundle/deployment/bind/postgres_database/output.txt | 2 -- .../bundle/deployment/bind/postgres_role/output.txt | 2 -- .../deployment/bind/postgres_snapshot_schedule/output.txt | 2 -- .../bundle/resources/postgres_branches/basic/output.txt | 4 ---- .../bundle/resources/postgres_catalogs/basic/output.txt | 2 -- .../bundle/resources/postgres_databases/basic/output.txt | 8 -------- .../bundle/resources/postgres_endpoints/basic/output.txt | 6 ------ .../bundle/resources/postgres_projects/basic/output.txt | 2 -- .../bundle/resources/postgres_roles/basic/output.txt | 6 ------ .../resources/postgres_synced_tables/basic/output.txt | 2 -- bundle/render/render_text_output.go | 4 +++- bundle/render/render_text_output_test.go | 1 - 13 files changed, 4 insertions(+), 39 deletions(-) diff --git a/.nextchanges/bundles/url-not-supported.md b/.nextchanges/bundles/url-not-supported.md index 86cc00a1dd9..67135362796 100644 --- a/.nextchanges/bundles/url-not-supported.md +++ b/.nextchanges/bundles/url-not-supported.md @@ -1 +1 @@ -* Resources that do not support a workspace URL now report that in CLI commands, instead of misleading the user into thinking the resource is not deployed. ([#6583](https://github.com/databricks/cli/pull/6583)) +* CLI commands no longer imply that a resource whose type has no workspace URL is merely not deployed yet. ([#6583](https://github.com/databricks/cli/pull/6583)) diff --git a/acceptance/bundle/deployment/bind/postgres_database/output.txt b/acceptance/bundle/deployment/bind/postgres_database/output.txt index a71b003a889..72b43b9c2e3 100644 --- a/acceptance/bundle/deployment/bind/postgres_database/output.txt +++ b/acceptance/bundle/deployment/bind/postgres_database/output.txt @@ -13,7 +13,6 @@ Resources: Postgres databases: database1: Name: - URL: (not supported) >>> [CLI] bundle deployment unbind database1 @@ -27,4 +26,3 @@ Resources: Postgres databases: database1: Name: - URL: (not supported) diff --git a/acceptance/bundle/deployment/bind/postgres_role/output.txt b/acceptance/bundle/deployment/bind/postgres_role/output.txt index fb8ab92a0cc..cea418c36e2 100644 --- a/acceptance/bundle/deployment/bind/postgres_role/output.txt +++ b/acceptance/bundle/deployment/bind/postgres_role/output.txt @@ -13,7 +13,6 @@ Resources: Postgres roles: role1: Name: - URL: (not supported) >>> [CLI] bundle deployment unbind role1 @@ -27,4 +26,3 @@ Resources: Postgres roles: role1: Name: - URL: (not supported) diff --git a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt index 01098097e95..5033cd73dfc 100644 --- a/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt +++ b/acceptance/bundle/deployment/bind/postgres_snapshot_schedule/output.txt @@ -13,7 +13,6 @@ Resources: Postgres snapshot schedules: schedule1: Name: projects/test-project/branches/main/snapshot-schedule - URL: (not supported) >>> [CLI] bundle deployment unbind schedule1 @@ -27,4 +26,3 @@ Resources: Postgres snapshot schedules: schedule1: Name: - URL: (not supported) diff --git a/acceptance/bundle/resources/postgres_branches/basic/output.txt b/acceptance/bundle/resources/postgres_branches/basic/output.txt index b4d86e3680e..cff6773cf76 100644 --- a/acceptance/bundle/resources/postgres_branches/basic/output.txt +++ b/acceptance/bundle/resources/postgres_branches/basic/output.txt @@ -18,11 +18,9 @@ Resources: Postgres branches: main: Name: - URL: (not supported) Postgres projects: my_project: Name: Test Project for Branch - URL: (not supported) >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-postgres-branch-[UNIQUE_NAME]/default/files... @@ -59,11 +57,9 @@ Resources: Postgres branches: main: Name: - URL: (not supported) Postgres projects: my_project: Name: Test Project for Branch - URL: (not supported) >>> print_requests.py --del-body project_id,branch_id,endpoint_id,database_id,role_id,catalog_id,synced_table_id --keep --get //postgres ^//workspace-files/ ^//workspace/ ^//telemetry-ext ^//operations/ diff --git a/acceptance/bundle/resources/postgres_catalogs/basic/output.txt b/acceptance/bundle/resources/postgres_catalogs/basic/output.txt index b45d875d867..dbc8e80e82f 100644 --- a/acceptance/bundle/resources/postgres_catalogs/basic/output.txt +++ b/acceptance/bundle/resources/postgres_catalogs/basic/output.txt @@ -22,7 +22,6 @@ Resources: Postgres projects: my_project: Name: Test Project for Catalog - URL: (not supported) >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-postgres-catalog-[UNIQUE_NAME]/default/files... @@ -56,7 +55,6 @@ Resources: Postgres projects: my_project: Name: Test Project for Catalog - URL: (not supported) >>> print_requests.py --del-body project_id,branch_id,endpoint_id,database_id,role_id,catalog_id,synced_table_id --keep --get //postgres ^//workspace-files/ ^//workspace/ ^//telemetry-ext ^//operations/ diff --git a/acceptance/bundle/resources/postgres_databases/basic/output.txt b/acceptance/bundle/resources/postgres_databases/basic/output.txt index 655c0d6979d..42d3dfa4e4e 100644 --- a/acceptance/bundle/resources/postgres_databases/basic/output.txt +++ b/acceptance/bundle/resources/postgres_databases/basic/output.txt @@ -18,19 +18,15 @@ Resources: Postgres branches: main: Name: - URL: (not supported) Postgres databases: my_database: Name: - URL: (not supported) Postgres projects: my_project: Name: Test Project for Database - URL: (not supported) Postgres roles: owner: Name: - URL: (not supported) >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-postgres-database-[UNIQUE_NAME]/default/files... @@ -63,19 +59,15 @@ Resources: Postgres branches: main: Name: - URL: (not supported) Postgres databases: my_database: Name: - URL: (not supported) Postgres projects: my_project: Name: Test Project for Database - URL: (not supported) Postgres roles: owner: Name: - URL: (not supported) >>> print_requests.py --del-body project_id,branch_id,endpoint_id,database_id,role_id,catalog_id,synced_table_id --keep --get //postgres ^//workspace-files/ ^//workspace/ ^//telemetry-ext ^//operations/ diff --git a/acceptance/bundle/resources/postgres_endpoints/basic/output.txt b/acceptance/bundle/resources/postgres_endpoints/basic/output.txt index 90f898d71dc..2a9c7fa37db 100644 --- a/acceptance/bundle/resources/postgres_endpoints/basic/output.txt +++ b/acceptance/bundle/resources/postgres_endpoints/basic/output.txt @@ -18,15 +18,12 @@ Resources: Postgres branches: main: Name: - URL: (not supported) Postgres endpoints: custom: Name: - URL: (not supported) Postgres projects: my_project: Name: Test Project for Endpoint - URL: (not supported) >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-postgres-endpoint-[UNIQUE_NAME]/default/files... @@ -61,15 +58,12 @@ Resources: Postgres branches: main: Name: - URL: (not supported) Postgres endpoints: custom: Name: - URL: (not supported) Postgres projects: my_project: Name: Test Project for Endpoint - URL: (not supported) >>> print_requests.py --del-body project_id,branch_id,endpoint_id,database_id,role_id,catalog_id,synced_table_id --keep --get //postgres ^//workspace-files/ ^//workspace/ ^//telemetry-ext ^//operations/ diff --git a/acceptance/bundle/resources/postgres_projects/basic/output.txt b/acceptance/bundle/resources/postgres_projects/basic/output.txt index 5a42cdb2be5..6fe7c79ee6b 100644 --- a/acceptance/bundle/resources/postgres_projects/basic/output.txt +++ b/acceptance/bundle/resources/postgres_projects/basic/output.txt @@ -18,7 +18,6 @@ Resources: Postgres projects: my_project: Name: Test Postgres Project - URL: (not supported) >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-postgres-single-project-[UNIQUE_NAME]/default/files... @@ -59,7 +58,6 @@ Resources: Postgres projects: my_project: Name: Test Postgres Project - URL: (not supported) >>> print_requests.py --del-body project_id,branch_id,endpoint_id,database_id,role_id,catalog_id,synced_table_id --keep --get //postgres ^//workspace-files/ ^//workspace/ ^//telemetry-ext ^//operations/ diff --git a/acceptance/bundle/resources/postgres_roles/basic/output.txt b/acceptance/bundle/resources/postgres_roles/basic/output.txt index 3edfde9d20d..979bb99ca15 100644 --- a/acceptance/bundle/resources/postgres_roles/basic/output.txt +++ b/acceptance/bundle/resources/postgres_roles/basic/output.txt @@ -18,15 +18,12 @@ Resources: Postgres branches: main: Name: - URL: (not supported) Postgres projects: my_project: Name: Test Project for Role - URL: (not supported) Postgres roles: my_role: Name: - URL: (not supported) >>> [CLI] bundle deploy Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/deploy-postgres-role-[UNIQUE_NAME]/default/files... @@ -67,15 +64,12 @@ Resources: Postgres branches: main: Name: - URL: (not supported) Postgres projects: my_project: Name: Test Project for Role - URL: (not supported) Postgres roles: my_role: Name: - URL: (not supported) >>> print_requests.py --del-body project_id,branch_id,endpoint_id,database_id,role_id,catalog_id,synced_table_id --keep --get //postgres ^//workspace-files/ ^//workspace/ ^//telemetry-ext ^//operations/ diff --git a/acceptance/bundle/resources/postgres_synced_tables/basic/output.txt b/acceptance/bundle/resources/postgres_synced_tables/basic/output.txt index 53e5fbc19a1..9916219e124 100644 --- a/acceptance/bundle/resources/postgres_synced_tables/basic/output.txt +++ b/acceptance/bundle/resources/postgres_synced_tables/basic/output.txt @@ -26,7 +26,6 @@ Resources: Postgres projects: my_project: Name: Test Project for Synced Table - URL: (not supported) Postgres synced tables: my_table: Name: ${resources.postgres_catalogs.my_catalog.catalog_id}.public.trips_synced @@ -65,7 +64,6 @@ Resources: Postgres projects: my_project: Name: Test Project for Synced Table - URL: (not supported) Postgres synced tables: my_table: Name: lakebase_test_[UNIQUE_NAME].public.trips_synced diff --git a/bundle/render/render_text_output.go b/bundle/render/render_text_output.go index 767e5853d8d..27ae5b6f7c5 100644 --- a/bundle/render/render_text_output.go +++ b/bundle/render/render_text_output.go @@ -40,7 +40,9 @@ const resourcesTemplate = `Resources: {{- range .Resources }} {{ .Key | bold }}: Name: {{ .Name }} - URL: {{ if .URL }}{{ .URL | cyan }}{{ else if .SupportsURL }}{{ "(not deployed)" | cyan }}{{ else }}{{ "(not supported)" | cyan }}{{ end }} + {{- if .SupportsURL }} + URL: {{ if .URL }}{{ .URL | cyan }}{{ else }}{{ "(not deployed)" | cyan }}{{ end }} + {{- end }} {{- end }} {{- end }} ` diff --git a/bundle/render/render_text_output_test.go b/bundle/render/render_text_output_test.go index c6e29126a47..192a95c108b 100644 --- a/bundle/render/render_text_output_test.go +++ b/bundle/render/render_text_output_test.go @@ -379,7 +379,6 @@ Resources: Secret Scopes: scope1: Name: my_scope - URL: (not supported) ` assert.Equal(t, expectedSummary, writer.String()) }