diff --git a/.codegen/_openapi_sha b/.codegen/_openapi_sha index 6d4ada17b..b3b30deca 100644 --- a/.codegen/_openapi_sha +++ b/.codegen/_openapi_sha @@ -1 +1 @@ -8f5eedbc991c4f04ce1284406577b0c92d59a224 \ No newline at end of file +d73c8f03963dfc2e1a3137124ecab243777f3dd2 \ No newline at end of file diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index c6b4db8a5..f637b2f19 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -37,3 +37,12 @@ * [Breaking] Change `destinations` field for `databricks.sdk.service.catalog.AccessRequestDestinations` to no longer be required. * Change `destinations` field for `databricks.sdk.service.catalog.AccessRequestDestinations` to no longer be required. * [Breaking] Change `online_store_config` field for `databricks.sdk.service.ml.MaterializedFeature` to type `databricks.sdk.service.ml.OnlineStoreConfig` dataclass. +* Add [w.workspace_entity_tag_assignments](https://databricks-sdk-py.readthedocs.io/en/latest/workspace/tags/workspace_entity_tag_assignments.html) workspace-level service. +* Add `clone()` method for [w.pipelines](https://databricks-sdk-py.readthedocs.io/en/latest/workspace/pipelines/pipelines.html) workspace-level service. +* Add `dataset_catalog` and `dataset_schema` fields for `databricks.sdk.service.dashboards.CreateDashboardRequest`. +* Add `dataset_catalog` and `dataset_schema` fields for `databricks.sdk.service.dashboards.UpdateDashboardRequest`. +* Add `purge_data` field for `databricks.sdk.service.database.DeleteSyncedDatabaseTableRequest`. +* Add `truncation` field for `databricks.sdk.service.pipelines.PipelineEvent`. +* Add `gcp_service_account` field for `databricks.sdk.service.provisioning.CreateGcpKeyInfo`. +* Add `gcp_service_account` field for `databricks.sdk.service.provisioning.GcpKeyInfo`. +* Add `foreign_table` and `volume` enum values for `databricks.sdk.service.sharing.SharedDataObjectDataObjectType`. \ No newline at end of file diff --git a/databricks/sdk/__init__.py b/databricks/sdk/__init__.py index 8067265a3..0474cbe7b 100755 --- a/databricks/sdk/__init__.py +++ b/databricks/sdk/__init__.py @@ -156,7 +156,8 @@ QueryVisualizationsLegacyAPI, RedashConfigAPI, StatementExecutionAPI, WarehousesAPI) -from databricks.sdk.service.tags import TagPoliciesAPI +from databricks.sdk.service.tags import (TagPoliciesAPI, + WorkspaceEntityTagAssignmentsAPI) from databricks.sdk.service.vectorsearch import (VectorSearchEndpointsAPI, VectorSearchIndexesAPI) from databricks.sdk.service.workspace import (GitCredentialsAPI, ReposAPI, @@ -386,6 +387,7 @@ def __init__( self._workspace = WorkspaceExt(self._api_client) self._workspace_bindings = pkg_catalog.WorkspaceBindingsAPI(self._api_client) self._workspace_conf = pkg_settings.WorkspaceConfAPI(self._api_client) + self._workspace_entity_tag_assignments = pkg_tags.WorkspaceEntityTagAssignmentsAPI(self._api_client) self._workspace_iam_v2 = pkg_iamv2.WorkspaceIamV2API(self._api_client) self._workspace_settings_v2 = pkg_settingsv2.WorkspaceSettingsV2API(self._api_client) self._groups = pkg_iam.GroupsAPI(self._api_client) @@ -989,6 +991,11 @@ def workspace_conf(self) -> pkg_settings.WorkspaceConfAPI: """This API allows updating known workspace settings for advanced users.""" return self._workspace_conf + @property + def workspace_entity_tag_assignments(self) -> pkg_tags.WorkspaceEntityTagAssignmentsAPI: + """Manage tag assignments on workspace-scoped objects.""" + return self._workspace_entity_tag_assignments + @property def workspace_iam_v2(self) -> pkg_iamv2.WorkspaceIamV2API: """These APIs are used to manage identities and the workspace access of these identities in .""" diff --git a/databricks/sdk/service/catalog.py b/databricks/sdk/service/catalog.py index 1e5276d26..197762d17 100755 --- a/databricks/sdk/service/catalog.py +++ b/databricks/sdk/service/catalog.py @@ -1740,7 +1740,7 @@ def from_dict(cls, d: Dict[str, Any]) -> ConnectionInfo: class ConnectionType(Enum): - """Next Id: 48""" + """Next Id: 49""" BIGQUERY = "BIGQUERY" DATABRICKS = "DATABRICKS" @@ -8744,7 +8744,7 @@ def from_dict(cls, d: Dict[str, Any]) -> Securable: class SecurableKind(Enum): - """Latest kind: SECRET_EXTERNAL_AWS_SECRETS_MANAGER = 273; Next id:274""" + """Latest kind: CONNECTION_SLACK_AUDIT_LOGS_OAUTH_U2M = 276; Next id:277""" TABLE_DB_STORAGE = "TABLE_DB_STORAGE" TABLE_DELTA = "TABLE_DELTA" diff --git a/databricks/sdk/service/compute.py b/databricks/sdk/service/compute.py index 473c7cca1..a6e062229 100755 --- a/databricks/sdk/service/compute.py +++ b/databricks/sdk/service/compute.py @@ -623,8 +623,7 @@ class ClusterAttributes: enable_elastic_disk: Optional[bool] = None """Autoscaling Local Storage: when enabled, this cluster will dynamically acquire additional disk - space when its Spark workers are running low on disk space. This feature requires specific AWS - permissions to function correctly - refer to the User Guide for more details.""" + space when its Spark workers are running low on disk space.""" enable_local_disk_encryption: Optional[bool] = None """Whether to enable LUKS on cluster VMs' local disks""" @@ -1018,8 +1017,7 @@ class ClusterDetails: enable_elastic_disk: Optional[bool] = None """Autoscaling Local Storage: when enabled, this cluster will dynamically acquire additional disk - space when its Spark workers are running low on disk space. This feature requires specific AWS - permissions to function correctly - refer to the User Guide for more details.""" + space when its Spark workers are running low on disk space.""" enable_local_disk_encryption: Optional[bool] = None """Whether to enable LUKS on cluster VMs' local disks""" @@ -2083,8 +2081,7 @@ class ClusterSpec: enable_elastic_disk: Optional[bool] = None """Autoscaling Local Storage: when enabled, this cluster will dynamically acquire additional disk - space when its Spark workers are running low on disk space. This feature requires specific AWS - permissions to function correctly - refer to the User Guide for more details.""" + space when its Spark workers are running low on disk space.""" enable_local_disk_encryption: Optional[bool] = None """Whether to enable LUKS on cluster VMs' local disks""" @@ -7341,8 +7338,7 @@ class UpdateClusterResource: enable_elastic_disk: Optional[bool] = None """Autoscaling Local Storage: when enabled, this cluster will dynamically acquire additional disk - space when its Spark workers are running low on disk space. This feature requires specific AWS - permissions to function correctly - refer to the User Guide for more details.""" + space when its Spark workers are running low on disk space.""" enable_local_disk_encryption: Optional[bool] = None """Whether to enable LUKS on cluster VMs' local disks""" @@ -8271,8 +8267,7 @@ def create( node_type_id take precedence. :param enable_elastic_disk: bool (optional) Autoscaling Local Storage: when enabled, this cluster will dynamically acquire additional disk space - when its Spark workers are running low on disk space. This feature requires specific AWS permissions - to function correctly - refer to the User Guide for more details. + when its Spark workers are running low on disk space. :param enable_local_disk_encryption: bool (optional) Whether to enable LUKS on cluster VMs' local disks :param gcp_attributes: :class:`GcpAttributes` (optional) @@ -8636,8 +8631,7 @@ def edit( node_type_id take precedence. :param enable_elastic_disk: bool (optional) Autoscaling Local Storage: when enabled, this cluster will dynamically acquire additional disk space - when its Spark workers are running low on disk space. This feature requires specific AWS permissions - to function correctly - refer to the User Guide for more details. + when its Spark workers are running low on disk space. :param enable_local_disk_encryption: bool (optional) Whether to enable LUKS on cluster VMs' local disks :param gcp_attributes: :class:`GcpAttributes` (optional) diff --git a/databricks/sdk/service/dashboards.py b/databricks/sdk/service/dashboards.py index 12c519dca..9b2f2f827 100755 --- a/databricks/sdk/service/dashboards.py +++ b/databricks/sdk/service/dashboards.py @@ -2315,21 +2315,36 @@ class LakeviewAPI: def __init__(self, api_client): self._api = api_client - def create(self, dashboard: Dashboard) -> Dashboard: + def create( + self, dashboard: Dashboard, *, dataset_catalog: Optional[str] = None, dataset_schema: Optional[str] = None + ) -> Dashboard: """Create a draft dashboard. :param dashboard: :class:`Dashboard` + :param dataset_catalog: str (optional) + Sets the default catalog for all datasets in this dashboard. Does not impact table references that + use fully qualified catalog names (ex: samples.nyctaxi.trips). Leave blank to keep each dataset’s + existing configuration. + :param dataset_schema: str (optional) + Sets the default schema for all datasets in this dashboard. Does not impact table references that + use fully qualified schema names (ex: nyctaxi.trips). Leave blank to keep each dataset’s existing + configuration. :returns: :class:`Dashboard` """ body = dashboard.as_dict() + query = {} + if dataset_catalog is not None: + query["dataset_catalog"] = dataset_catalog + if dataset_schema is not None: + query["dataset_schema"] = dataset_schema headers = { "Accept": "application/json", "Content-Type": "application/json", } - res = self._api.do("POST", "/api/2.0/lakeview/dashboards", body=body, headers=headers) + res = self._api.do("POST", "/api/2.0/lakeview/dashboards", query=query, body=body, headers=headers) return Dashboard.from_dict(res) def create_schedule(self, dashboard_id: str, schedule: Schedule) -> Schedule: @@ -2737,23 +2752,45 @@ def unpublish(self, dashboard_id: str): self._api.do("DELETE", f"/api/2.0/lakeview/dashboards/{dashboard_id}/published", headers=headers) - def update(self, dashboard_id: str, dashboard: Dashboard) -> Dashboard: + def update( + self, + dashboard_id: str, + dashboard: Dashboard, + *, + dataset_catalog: Optional[str] = None, + dataset_schema: Optional[str] = None, + ) -> Dashboard: """Update a draft dashboard. :param dashboard_id: str UUID identifying the dashboard. :param dashboard: :class:`Dashboard` + :param dataset_catalog: str (optional) + Sets the default catalog for all datasets in this dashboard. Does not impact table references that + use fully qualified catalog names (ex: samples.nyctaxi.trips). Leave blank to keep each dataset’s + existing configuration. + :param dataset_schema: str (optional) + Sets the default schema for all datasets in this dashboard. Does not impact table references that + use fully qualified schema names (ex: nyctaxi.trips). Leave blank to keep each dataset’s existing + configuration. :returns: :class:`Dashboard` """ body = dashboard.as_dict() + query = {} + if dataset_catalog is not None: + query["dataset_catalog"] = dataset_catalog + if dataset_schema is not None: + query["dataset_schema"] = dataset_schema headers = { "Accept": "application/json", "Content-Type": "application/json", } - res = self._api.do("PATCH", f"/api/2.0/lakeview/dashboards/{dashboard_id}", body=body, headers=headers) + res = self._api.do( + "PATCH", f"/api/2.0/lakeview/dashboards/{dashboard_id}", query=query, body=body, headers=headers + ) return Dashboard.from_dict(res) def update_schedule(self, dashboard_id: str, schedule_id: str, schedule: Schedule) -> Schedule: diff --git a/databricks/sdk/service/database.py b/databricks/sdk/service/database.py index 21d6ea9c9..3487bd80c 100755 --- a/databricks/sdk/service/database.py +++ b/databricks/sdk/service/database.py @@ -1772,19 +1772,24 @@ def delete_database_table(self, name: str): self._api.do("DELETE", f"/api/2.0/database/tables/{name}", headers=headers) - def delete_synced_database_table(self, name: str): + def delete_synced_database_table(self, name: str, *, purge_data: Optional[bool] = None): """Delete a Synced Database Table. :param name: str + :param purge_data: bool (optional) + Optional. When set to true, the actual PostgreSQL table will be dropped from the database. """ + query = {} + if purge_data is not None: + query["purge_data"] = purge_data headers = { "Accept": "application/json", } - self._api.do("DELETE", f"/api/2.0/database/synced_tables/{name}", headers=headers) + self._api.do("DELETE", f"/api/2.0/database/synced_tables/{name}", query=query, headers=headers) def find_database_instance_by_uid(self, *, uid: Optional[str] = None) -> DatabaseInstance: """Find a Database Instance by uid. diff --git a/databricks/sdk/service/pipelines.py b/databricks/sdk/service/pipelines.py index d38088dda..4dcd2a656 100755 --- a/databricks/sdk/service/pipelines.py +++ b/databricks/sdk/service/pipelines.py @@ -22,6 +22,31 @@ # all definitions in this file are in alphabetical order +@dataclass +class ClonePipelineResponse: + pipeline_id: Optional[str] = None + """The pipeline id of the cloned pipeline""" + + def as_dict(self) -> dict: + """Serializes the ClonePipelineResponse into a dictionary suitable for use as a JSON request body.""" + body = {} + if self.pipeline_id is not None: + body["pipeline_id"] = self.pipeline_id + return body + + def as_shallow_dict(self) -> dict: + """Serializes the ClonePipelineResponse into a shallow dictionary of its immediate attributes.""" + body = {} + if self.pipeline_id is not None: + body["pipeline_id"] = self.pipeline_id + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> ClonePipelineResponse: + """Deserializes the ClonePipelineResponse from a dictionary.""" + return cls(pipeline_id=d.get("pipeline_id", None)) + + @dataclass class ConnectionParameters: source_catalog: Optional[str] = None @@ -1720,6 +1745,11 @@ class PipelineEvent: timestamp: Optional[str] = None """The time of the event.""" + truncation: Optional[Truncation] = None + """Information about which fields were truncated from this event due to size constraints. If empty + or absent, no truncation occurred. See https://docs.databricks.com/en/ldp/monitor-event-logs for + information on retrieving complete event data.""" + def as_dict(self) -> dict: """Serializes the PipelineEvent into a dictionary suitable for use as a JSON request body.""" body = {} @@ -1741,6 +1771,8 @@ def as_dict(self) -> dict: body["sequence"] = self.sequence.as_dict() if self.timestamp is not None: body["timestamp"] = self.timestamp + if self.truncation: + body["truncation"] = self.truncation.as_dict() return body def as_shallow_dict(self) -> dict: @@ -1764,6 +1796,8 @@ def as_shallow_dict(self) -> dict: body["sequence"] = self.sequence if self.timestamp is not None: body["timestamp"] = self.timestamp + if self.truncation: + body["truncation"] = self.truncation return body @classmethod @@ -1779,6 +1813,7 @@ def from_dict(cls, d: Dict[str, Any]) -> PipelineEvent: origin=_from_dict(d, "origin", Origin), sequence=_from_dict(d, "sequence", Sequencing), timestamp=d.get("timestamp", None), + truncation=_from_dict(d, "truncation", Truncation), ) @@ -3181,6 +3216,60 @@ class TableSpecificConfigScdType(Enum): SCD_TYPE_2 = "SCD_TYPE_2" +@dataclass +class Truncation: + """Information about truncations applied to this event.""" + + truncated_fields: Optional[List[TruncationTruncationDetail]] = None + """List of fields that were truncated from this event. If empty or absent, no truncation occurred.""" + + def as_dict(self) -> dict: + """Serializes the Truncation into a dictionary suitable for use as a JSON request body.""" + body = {} + if self.truncated_fields: + body["truncated_fields"] = [v.as_dict() for v in self.truncated_fields] + return body + + def as_shallow_dict(self) -> dict: + """Serializes the Truncation into a shallow dictionary of its immediate attributes.""" + body = {} + if self.truncated_fields: + body["truncated_fields"] = self.truncated_fields + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> Truncation: + """Deserializes the Truncation from a dictionary.""" + return cls(truncated_fields=_repeated_dict(d, "truncated_fields", TruncationTruncationDetail)) + + +@dataclass +class TruncationTruncationDetail: + """Details about a specific field that was truncated.""" + + field_name: Optional[str] = None + """The name of the truncated field (e.g., "error"). Corresponds to field names in PipelineEvent.""" + + def as_dict(self) -> dict: + """Serializes the TruncationTruncationDetail into a dictionary suitable for use as a JSON request body.""" + body = {} + if self.field_name is not None: + body["field_name"] = self.field_name + return body + + def as_shallow_dict(self) -> dict: + """Serializes the TruncationTruncationDetail into a shallow dictionary of its immediate attributes.""" + body = {} + if self.field_name is not None: + body["field_name"] = self.field_name + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> TruncationTruncationDetail: + """Deserializes the TruncationTruncationDetail from a dictionary.""" + return cls(field_name=d.get("field_name", None)) + + @dataclass class UpdateInfo: cause: Optional[UpdateInfoCause] = None @@ -3426,6 +3515,189 @@ def wait_get_pipeline_idle( attempt += 1 raise TimeoutError(f"timed out after {timeout}: {status_message}") + def clone( + self, + pipeline_id: str, + *, + allow_duplicate_names: Optional[bool] = None, + budget_policy_id: Optional[str] = None, + catalog: Optional[str] = None, + channel: Optional[str] = None, + clusters: Optional[List[PipelineCluster]] = None, + configuration: Optional[Dict[str, str]] = None, + continuous: Optional[bool] = None, + deployment: Optional[PipelineDeployment] = None, + development: Optional[bool] = None, + edition: Optional[str] = None, + environment: Optional[PipelinesEnvironment] = None, + event_log: Optional[EventLogSpec] = None, + expected_last_modified: Optional[int] = None, + filters: Optional[Filters] = None, + gateway_definition: Optional[IngestionGatewayPipelineDefinition] = None, + id: Optional[str] = None, + ingestion_definition: Optional[IngestionPipelineDefinition] = None, + libraries: Optional[List[PipelineLibrary]] = None, + name: Optional[str] = None, + notifications: Optional[List[Notifications]] = None, + photon: Optional[bool] = None, + restart_window: Optional[RestartWindow] = None, + root_path: Optional[str] = None, + schema: Optional[str] = None, + serverless: Optional[bool] = None, + storage: Optional[str] = None, + tags: Optional[Dict[str, str]] = None, + target: Optional[str] = None, + trigger: Optional[PipelineTrigger] = None, + usage_policy_id: Optional[str] = None, + ) -> ClonePipelineResponse: + """Creates a new pipeline using Unity Catalog from a pipeline using Hive Metastore. This method returns + the ID of the newly created clone. Additionally, this method starts an update for the newly created + pipeline. + + :param pipeline_id: str + Source pipeline to clone from + :param allow_duplicate_names: bool (optional) + If false, deployment will fail if name conflicts with that of another pipeline. + :param budget_policy_id: str (optional) + Budget policy of this pipeline. + :param catalog: str (optional) + A catalog in Unity Catalog to publish data from this pipeline to. If `target` is specified, tables + in this pipeline are published to a `target` schema inside `catalog` (for example, + `catalog`.`target`.`table`). If `target` is not specified, no data is published to Unity Catalog. + :param channel: str (optional) + DLT Release Channel that specifies which version to use. + :param clusters: List[:class:`PipelineCluster`] (optional) + Cluster settings for this pipeline deployment. + :param configuration: Dict[str,str] (optional) + String-String configuration for this pipeline execution. + :param continuous: bool (optional) + Whether the pipeline is continuous or triggered. This replaces `trigger`. + :param deployment: :class:`PipelineDeployment` (optional) + Deployment type of this pipeline. + :param development: bool (optional) + Whether the pipeline is in Development mode. Defaults to false. + :param edition: str (optional) + Pipeline product edition. + :param environment: :class:`PipelinesEnvironment` (optional) + Environment specification for this pipeline used to install dependencies. + :param event_log: :class:`EventLogSpec` (optional) + Event log configuration for this pipeline + :param expected_last_modified: int (optional) + If present, the last-modified time of the pipeline settings before the clone. If the settings were + modified after that time, then the request will fail with a conflict. + :param filters: :class:`Filters` (optional) + Filters on which Pipeline packages to include in the deployed graph. + :param gateway_definition: :class:`IngestionGatewayPipelineDefinition` (optional) + The definition of a gateway pipeline to support change data capture. + :param id: str (optional) + Unique identifier for this pipeline. + :param ingestion_definition: :class:`IngestionPipelineDefinition` (optional) + The configuration for a managed ingestion pipeline. These settings cannot be used with the + 'libraries', 'schema', 'target', or 'catalog' settings. + :param libraries: List[:class:`PipelineLibrary`] (optional) + Libraries or code needed by this deployment. + :param name: str (optional) + Friendly identifier for this pipeline. + :param notifications: List[:class:`Notifications`] (optional) + List of notification settings for this pipeline. + :param photon: bool (optional) + Whether Photon is enabled for this pipeline. + :param restart_window: :class:`RestartWindow` (optional) + Restart window of this pipeline. + :param root_path: str (optional) + Root path for this pipeline. This is used as the root directory when editing the pipeline in the + Databricks user interface and it is added to sys.path when executing Python sources during pipeline + execution. + :param schema: str (optional) + The default schema (database) where tables are read from or published to. + :param serverless: bool (optional) + Whether serverless compute is enabled for this pipeline. + :param storage: str (optional) + DBFS root directory for storing checkpoints and tables. + :param tags: Dict[str,str] (optional) + A map of tags associated with the pipeline. These are forwarded to the cluster as cluster tags, and + are therefore subject to the same limitations. A maximum of 25 tags can be added to the pipeline. + :param target: str (optional) + Target schema (database) to add tables in this pipeline to. Exactly one of `schema` or `target` must + be specified. To publish to Unity Catalog, also specify `catalog`. This legacy field is deprecated + for pipeline creation in favor of the `schema` field. + :param trigger: :class:`PipelineTrigger` (optional) + Which pipeline trigger to use. Deprecated: Use `continuous` instead. + :param usage_policy_id: str (optional) + Usage policy of this pipeline. + + :returns: :class:`ClonePipelineResponse` + """ + + body = {} + if allow_duplicate_names is not None: + body["allow_duplicate_names"] = allow_duplicate_names + if budget_policy_id is not None: + body["budget_policy_id"] = budget_policy_id + if catalog is not None: + body["catalog"] = catalog + if channel is not None: + body["channel"] = channel + if clusters is not None: + body["clusters"] = [v.as_dict() for v in clusters] + if configuration is not None: + body["configuration"] = configuration + if continuous is not None: + body["continuous"] = continuous + if deployment is not None: + body["deployment"] = deployment.as_dict() + if development is not None: + body["development"] = development + if edition is not None: + body["edition"] = edition + if environment is not None: + body["environment"] = environment.as_dict() + if event_log is not None: + body["event_log"] = event_log.as_dict() + if expected_last_modified is not None: + body["expected_last_modified"] = expected_last_modified + if filters is not None: + body["filters"] = filters.as_dict() + if gateway_definition is not None: + body["gateway_definition"] = gateway_definition.as_dict() + if id is not None: + body["id"] = id + if ingestion_definition is not None: + body["ingestion_definition"] = ingestion_definition.as_dict() + if libraries is not None: + body["libraries"] = [v.as_dict() for v in libraries] + if name is not None: + body["name"] = name + if notifications is not None: + body["notifications"] = [v.as_dict() for v in notifications] + if photon is not None: + body["photon"] = photon + if restart_window is not None: + body["restart_window"] = restart_window.as_dict() + if root_path is not None: + body["root_path"] = root_path + if schema is not None: + body["schema"] = schema + if serverless is not None: + body["serverless"] = serverless + if storage is not None: + body["storage"] = storage + if tags is not None: + body["tags"] = tags + if target is not None: + body["target"] = target + if trigger is not None: + body["trigger"] = trigger.as_dict() + if usage_policy_id is not None: + body["usage_policy_id"] = usage_policy_id + headers = { + "Accept": "application/json", + "Content-Type": "application/json", + } + + res = self._api.do("POST", f"/api/2.0/pipelines/{pipeline_id}/clone", body=body, headers=headers) + return ClonePipelineResponse.from_dict(res) + def create( self, *, diff --git a/databricks/sdk/service/provisioning.py b/databricks/sdk/service/provisioning.py index a2e651647..89e516f35 100755 --- a/databricks/sdk/service/provisioning.py +++ b/databricks/sdk/service/provisioning.py @@ -331,9 +331,15 @@ class CreateGcpKeyInfo: """Globally unique kms key resource id of the form projects/testProjectId/locations/us-east4/keyRings/gcpCmkKeyRing/cryptoKeys/cmk-eastus4""" + gcp_service_account: Optional[GcpServiceAccount] = None + """Globally unique service account email that has access to the KMS key. The service account exists + within the Databricks CP project.""" + def as_dict(self) -> dict: """Serializes the CreateGcpKeyInfo into a dictionary suitable for use as a JSON request body.""" body = {} + if self.gcp_service_account: + body["gcp_service_account"] = self.gcp_service_account.as_dict() if self.kms_key_id is not None: body["kms_key_id"] = self.kms_key_id return body @@ -341,6 +347,8 @@ def as_dict(self) -> dict: def as_shallow_dict(self) -> dict: """Serializes the CreateGcpKeyInfo into a shallow dictionary of its immediate attributes.""" body = {} + if self.gcp_service_account: + body["gcp_service_account"] = self.gcp_service_account if self.kms_key_id is not None: body["kms_key_id"] = self.kms_key_id return body @@ -348,7 +356,10 @@ def as_shallow_dict(self) -> dict: @classmethod def from_dict(cls, d: Dict[str, Any]) -> CreateGcpKeyInfo: """Deserializes the CreateGcpKeyInfo from a dictionary.""" - return cls(kms_key_id=d.get("kms_key_id", None)) + return cls( + gcp_service_account=_from_dict(d, "gcp_service_account", GcpServiceAccount), + kms_key_id=d.get("kms_key_id", None), + ) @dataclass @@ -582,9 +593,15 @@ class GcpKeyInfo: """Globally unique kms key resource id of the form projects/testProjectId/locations/us-east4/keyRings/gcpCmkKeyRing/cryptoKeys/cmk-eastus4""" + gcp_service_account: Optional[GcpServiceAccount] = None + """Globally unique service account email that has access to the KMS key. The service account exists + within the Databricks CP project.""" + def as_dict(self) -> dict: """Serializes the GcpKeyInfo into a dictionary suitable for use as a JSON request body.""" body = {} + if self.gcp_service_account: + body["gcp_service_account"] = self.gcp_service_account.as_dict() if self.kms_key_id is not None: body["kms_key_id"] = self.kms_key_id return body @@ -592,6 +609,8 @@ def as_dict(self) -> dict: def as_shallow_dict(self) -> dict: """Serializes the GcpKeyInfo into a shallow dictionary of its immediate attributes.""" body = {} + if self.gcp_service_account: + body["gcp_service_account"] = self.gcp_service_account if self.kms_key_id is not None: body["kms_key_id"] = self.kms_key_id return body @@ -599,7 +618,10 @@ def as_shallow_dict(self) -> dict: @classmethod def from_dict(cls, d: Dict[str, Any]) -> GcpKeyInfo: """Deserializes the GcpKeyInfo from a dictionary.""" - return cls(kms_key_id=d.get("kms_key_id", None)) + return cls( + gcp_service_account=_from_dict(d, "gcp_service_account", GcpServiceAccount), + kms_key_id=d.get("kms_key_id", None), + ) @dataclass @@ -716,6 +738,30 @@ def from_dict(cls, d: Dict[str, Any]) -> GcpNetworkInfo: ) +@dataclass +class GcpServiceAccount: + service_account_email: Optional[str] = None + + def as_dict(self) -> dict: + """Serializes the GcpServiceAccount into a dictionary suitable for use as a JSON request body.""" + body = {} + if self.service_account_email is not None: + body["service_account_email"] = self.service_account_email + return body + + def as_shallow_dict(self) -> dict: + """Serializes the GcpServiceAccount into a shallow dictionary of its immediate attributes.""" + body = {} + if self.service_account_email is not None: + body["service_account_email"] = self.service_account_email + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> GcpServiceAccount: + """Deserializes the GcpServiceAccount from a dictionary.""" + return cls(service_account_email=d.get("service_account_email", None)) + + @dataclass class GcpVpcEndpointInfo: project_id: str diff --git a/databricks/sdk/service/sharing.py b/databricks/sdk/service/sharing.py index bc2d78bc4..82d0e0cd4 100755 --- a/databricks/sdk/service/sharing.py +++ b/databricks/sdk/service/sharing.py @@ -2113,6 +2113,7 @@ def from_dict(cls, d: Dict[str, Any]) -> SharedDataObject: class SharedDataObjectDataObjectType(Enum): FEATURE_SPEC = "FEATURE_SPEC" + FOREIGN_TABLE = "FOREIGN_TABLE" FUNCTION = "FUNCTION" MATERIALIZED_VIEW = "MATERIALIZED_VIEW" MODEL = "MODEL" @@ -2121,6 +2122,7 @@ class SharedDataObjectDataObjectType(Enum): STREAMING_TABLE = "STREAMING_TABLE" TABLE = "TABLE" VIEW = "VIEW" + VOLUME = "VOLUME" class SharedDataObjectHistoryDataSharingStatus(Enum): diff --git a/databricks/sdk/service/sql.py b/databricks/sdk/service/sql.py index 403f401d3..7f7c69e0b 100755 --- a/databricks/sdk/service/sql.py +++ b/databricks/sdk/service/sql.py @@ -876,8 +876,11 @@ class AlertV2Notification: """Whether to notify alert subscribers when alert returns back to normal.""" retrigger_seconds: Optional[int] = None - """Number of seconds an alert must wait after being triggered to rearm itself. After rearming, it - can be triggered again. If 0 or not specified, the alert will not be triggered again.""" + """Number of seconds an alert waits after being triggered before it is allowed to send another + notification. If set to 0 or omitted, the alert will not send any further notifications after + the first trigger Setting this value to 1 allows the alert to send a notification on every + evaluation where the condition is met, effectively making it always retrigger for notification + purposes.""" subscriptions: Optional[List[AlertV2Subscription]] = None diff --git a/databricks/sdk/service/tags.py b/databricks/sdk/service/tags.py index 15102543d..274382190 100755 --- a/databricks/sdk/service/tags.py +++ b/databricks/sdk/service/tags.py @@ -14,6 +14,40 @@ # all definitions in this file are in alphabetical order +@dataclass +class ListTagAssignmentsResponse: + next_page_token: Optional[str] = None + """Pagination token to request the next page of tag assignments""" + + tag_assignments: Optional[List[TagAssignment]] = None + + def as_dict(self) -> dict: + """Serializes the ListTagAssignmentsResponse into a dictionary suitable for use as a JSON request body.""" + body = {} + if self.next_page_token is not None: + body["next_page_token"] = self.next_page_token + if self.tag_assignments: + body["tag_assignments"] = [v.as_dict() for v in self.tag_assignments] + return body + + def as_shallow_dict(self) -> dict: + """Serializes the ListTagAssignmentsResponse into a shallow dictionary of its immediate attributes.""" + body = {} + if self.next_page_token is not None: + body["next_page_token"] = self.next_page_token + if self.tag_assignments: + body["tag_assignments"] = self.tag_assignments + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> ListTagAssignmentsResponse: + """Deserializes the ListTagAssignmentsResponse from a dictionary.""" + return cls( + next_page_token=d.get("next_page_token", None), + tag_assignments=_repeated_dict(d, "tag_assignments", TagAssignment), + ) + + @dataclass class ListTagPoliciesResponse: next_page_token: Optional[str] = None @@ -46,6 +80,57 @@ def from_dict(cls, d: Dict[str, Any]) -> ListTagPoliciesResponse: ) +@dataclass +class TagAssignment: + entity_type: str + """The type of entity to which the tag is assigned. Allowed values are dashboards, geniespaces""" + + entity_id: str + """The identifier of the entity to which the tag is assigned""" + + tag_key: str + """The key of the tag. The characters , . : / - = and leading/trailing spaces are not allowed""" + + tag_value: Optional[str] = None + """The value of the tag""" + + def as_dict(self) -> dict: + """Serializes the TagAssignment into a dictionary suitable for use as a JSON request body.""" + body = {} + if self.entity_id is not None: + body["entity_id"] = self.entity_id + if self.entity_type is not None: + body["entity_type"] = self.entity_type + if self.tag_key is not None: + body["tag_key"] = self.tag_key + if self.tag_value is not None: + body["tag_value"] = self.tag_value + return body + + def as_shallow_dict(self) -> dict: + """Serializes the TagAssignment into a shallow dictionary of its immediate attributes.""" + body = {} + if self.entity_id is not None: + body["entity_id"] = self.entity_id + if self.entity_type is not None: + body["entity_type"] = self.entity_type + if self.tag_key is not None: + body["tag_key"] = self.tag_key + if self.tag_value is not None: + body["tag_value"] = self.tag_value + return body + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> TagAssignment: + """Deserializes the TagAssignment from a dictionary.""" + return cls( + entity_id=d.get("entity_id", None), + entity_type=d.get("entity_type", None), + tag_key=d.get("tag_key", None), + tag_value=d.get("tag_value", None), + ) + + @dataclass class TagPolicy: tag_key: str @@ -277,3 +362,151 @@ def update_tag_policy(self, tag_key: str, tag_policy: TagPolicy, update_mask: st res = self._api.do("PATCH", f"/api/2.1/tag-policies/{tag_key}", query=query, body=body, headers=headers) return TagPolicy.from_dict(res) + + +class WorkspaceEntityTagAssignmentsAPI: + """Manage tag assignments on workspace-scoped objects.""" + + def __init__(self, api_client): + self._api = api_client + + def create_tag_assignment(self, tag_assignment: TagAssignment) -> TagAssignment: + """Create a tag assignment + + :param tag_assignment: :class:`TagAssignment` + + :returns: :class:`TagAssignment` + """ + + body = tag_assignment.as_dict() + headers = { + "Accept": "application/json", + "Content-Type": "application/json", + } + + res = self._api.do("POST", "/api/2.0/entity-tag-assignments", body=body, headers=headers) + return TagAssignment.from_dict(res) + + def delete_tag_assignment(self, entity_type: str, entity_id: str, tag_key: str): + """Delete a tag assignment + + :param entity_type: str + The type of entity to which the tag is assigned. Allowed values are dashboards, geniespaces + :param entity_id: str + The identifier of the entity to which the tag is assigned + :param tag_key: str + The key of the tag. The characters , . : / - = and leading/trailing spaces are not allowed + + + """ + + headers = { + "Accept": "application/json", + } + + self._api.do( + "DELETE", f"/api/2.0/entity-tag-assignments/{entity_type}/{entity_id}/tags/{tag_key}", headers=headers + ) + + def get_tag_assignment(self, entity_type: str, entity_id: str, tag_key: str) -> TagAssignment: + """Get a tag assignment + + :param entity_type: str + The type of entity to which the tag is assigned. Allowed values are dashboards, geniespaces + :param entity_id: str + The identifier of the entity to which the tag is assigned + :param tag_key: str + The key of the tag. The characters , . : / - = and leading/trailing spaces are not allowed + + :returns: :class:`TagAssignment` + """ + + headers = { + "Accept": "application/json", + } + + res = self._api.do( + "GET", f"/api/2.0/entity-tag-assignments/{entity_type}/{entity_id}/tags/{tag_key}", headers=headers + ) + return TagAssignment.from_dict(res) + + def list_tag_assignments( + self, entity_type: str, entity_id: str, *, page_size: Optional[int] = None, page_token: Optional[str] = None + ) -> Iterator[TagAssignment]: + """List the tag assignments for an entity + + :param entity_type: str + The type of entity to which the tag is assigned. Allowed values are dashboards, geniespaces + :param entity_id: str + The identifier of the entity to which the tag is assigned + :param page_size: int (optional) + Optional. Maximum number of tag assignments to return in a single page + :param page_token: str (optional) + Pagination token to go to the next page of tag assignments. Requests first page if absent. + + :returns: Iterator over :class:`TagAssignment` + """ + + query = {} + if page_size is not None: + query["page_size"] = page_size + if page_token is not None: + query["page_token"] = page_token + headers = { + "Accept": "application/json", + } + + while True: + json = self._api.do( + "GET", f"/api/2.0/entity-tag-assignments/{entity_type}/{entity_id}/tags", query=query, headers=headers + ) + if "tag_assignments" in json: + for v in json["tag_assignments"]: + yield TagAssignment.from_dict(v) + if "next_page_token" not in json or not json["next_page_token"]: + return + query["page_token"] = json["next_page_token"] + + def update_tag_assignment( + self, entity_type: str, entity_id: str, tag_key: str, tag_assignment: TagAssignment, update_mask: str + ) -> TagAssignment: + """Update a tag assignment + + :param entity_type: str + The type of entity to which the tag is assigned. Allowed values are dashboards, geniespaces + :param entity_id: str + The identifier of the entity to which the tag is assigned + :param tag_key: str + The key of the tag. The characters , . : / - = and leading/trailing spaces are not allowed + :param tag_assignment: :class:`TagAssignment` + :param update_mask: str + 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`). Specification of elements in sequence or map fields is not allowed, as only + the entire collection field can be specified. Field names must exactly match the resource field + names. + + A field mask of `*` indicates full replacement. It’s recommended to always explicitly list the + fields being updated and avoid using `*` wildcards, as it can lead to unintended results if the API + changes in the future. + + :returns: :class:`TagAssignment` + """ + + body = tag_assignment.as_dict() + query = {} + if update_mask is not None: + query["update_mask"] = update_mask + headers = { + "Accept": "application/json", + "Content-Type": "application/json", + } + + res = self._api.do( + "PATCH", + f"/api/2.0/entity-tag-assignments/{entity_type}/{entity_id}/tags/{tag_key}", + query=query, + body=body, + headers=headers, + ) + return TagAssignment.from_dict(res) diff --git a/docs/account/iam/workspace_assignment.rst b/docs/account/iam/workspace_assignment.rst index ca78b86df..fa9c2ee3e 100644 --- a/docs/account/iam/workspace_assignment.rst +++ b/docs/account/iam/workspace_assignment.rst @@ -43,9 +43,9 @@ a = AccountClient() - workspace_id = os.environ["TEST_WORKSPACE_ID"] + workspace_id = os.environ["DUMMY_WORKSPACE_ID"] - all = a.workspace_assignment.list(list=workspace_id) + all = a.workspace_assignment.list(workspace_id=workspace_id) Get the permission assignments for the specified Databricks account and Databricks workspace. @@ -74,9 +74,9 @@ spn_id = spn.id - workspace_id = os.environ["TEST_WORKSPACE_ID"] + workspace_id = os.environ["DUMMY_WORKSPACE_ID"] - a.workspace_assignment.update( + _ = a.workspace_assignment.update( workspace_id=workspace_id, principal_id=spn_id, permissions=[iam.WorkspacePermission.USER], diff --git a/docs/account/provisioning/storage.rst b/docs/account/provisioning/storage.rst index 25ee5abaa..41a04deb3 100644 --- a/docs/account/provisioning/storage.rst +++ b/docs/account/provisioning/storage.rst @@ -23,10 +23,13 @@ a = AccountClient() - storage = a.storage.create( + bucket = a.storage.create( storage_configuration_name=f"sdk-{time.time_ns()}", root_bucket_info=provisioning.RootBucketInfo(bucket_name=f"sdk-{time.time_ns()}"), ) + + # cleanup + a.storage.delete(storage_configuration_id=bucket.storage_configuration_id) Creates a Databricks storage configuration for an account. diff --git a/docs/dbdataclasses/catalog.rst b/docs/dbdataclasses/catalog.rst index ca2bb65bb..171369e44 100644 --- a/docs/dbdataclasses/catalog.rst +++ b/docs/dbdataclasses/catalog.rst @@ -279,7 +279,7 @@ These dataclasses are used in the SDK to represent API requests and responses fo .. py:class:: ConnectionType - Next Id: 48 + Next Id: 49 .. py:attribute:: BIGQUERY :value: "BIGQUERY" @@ -1497,7 +1497,7 @@ These dataclasses are used in the SDK to represent API requests and responses fo .. py:class:: SecurableKind - Latest kind: SECRET_EXTERNAL_AWS_SECRETS_MANAGER = 273; Next id:274 + Latest kind: CONNECTION_SLACK_AUDIT_LOGS_OAUTH_U2M = 276; Next id:277 .. py:attribute:: TABLE_DB_STORAGE :value: "TABLE_DB_STORAGE" diff --git a/docs/dbdataclasses/pipelines.rst b/docs/dbdataclasses/pipelines.rst index cd6a437f8..c28965bf8 100644 --- a/docs/dbdataclasses/pipelines.rst +++ b/docs/dbdataclasses/pipelines.rst @@ -4,6 +4,10 @@ Delta Live Tables These dataclasses are used in the SDK to represent API requests and responses for services in the ``databricks.sdk.service.pipelines`` module. .. py:currentmodule:: databricks.sdk.service.pipelines +.. autoclass:: ClonePipelineResponse + :members: + :undoc-members: + .. autoclass:: ConnectionParameters :members: :undoc-members: @@ -459,6 +463,14 @@ These dataclasses are used in the SDK to represent API requests and responses fo .. py:attribute:: SCD_TYPE_2 :value: "SCD_TYPE_2" +.. autoclass:: Truncation + :members: + :undoc-members: + +.. autoclass:: TruncationTruncationDetail + :members: + :undoc-members: + .. autoclass:: UpdateInfo :members: :undoc-members: diff --git a/docs/dbdataclasses/provisioning.rst b/docs/dbdataclasses/provisioning.rst index 3ddcfcb42..d42456cb3 100644 --- a/docs/dbdataclasses/provisioning.rst +++ b/docs/dbdataclasses/provisioning.rst @@ -113,6 +113,10 @@ These dataclasses are used in the SDK to represent API requests and responses fo :members: :undoc-members: +.. autoclass:: GcpServiceAccount + :members: + :undoc-members: + .. autoclass:: GcpVpcEndpointInfo :members: :undoc-members: diff --git a/docs/dbdataclasses/sharing.rst b/docs/dbdataclasses/sharing.rst index a10c32072..17c824fd4 100644 --- a/docs/dbdataclasses/sharing.rst +++ b/docs/dbdataclasses/sharing.rst @@ -403,6 +403,9 @@ These dataclasses are used in the SDK to represent API requests and responses fo .. py:attribute:: FEATURE_SPEC :value: "FEATURE_SPEC" + .. py:attribute:: FOREIGN_TABLE + :value: "FOREIGN_TABLE" + .. py:attribute:: FUNCTION :value: "FUNCTION" @@ -427,6 +430,9 @@ These dataclasses are used in the SDK to represent API requests and responses fo .. py:attribute:: VIEW :value: "VIEW" + .. py:attribute:: VOLUME + :value: "VOLUME" + .. py:class:: SharedDataObjectHistoryDataSharingStatus .. py:attribute:: DISABLED diff --git a/docs/dbdataclasses/tags.rst b/docs/dbdataclasses/tags.rst index 23eb1d728..02892350f 100644 --- a/docs/dbdataclasses/tags.rst +++ b/docs/dbdataclasses/tags.rst @@ -4,10 +4,18 @@ Tags These dataclasses are used in the SDK to represent API requests and responses for services in the ``databricks.sdk.service.tags`` module. .. py:currentmodule:: databricks.sdk.service.tags +.. autoclass:: ListTagAssignmentsResponse + :members: + :undoc-members: + .. autoclass:: ListTagPoliciesResponse :members: :undoc-members: +.. autoclass:: TagAssignment + :members: + :undoc-members: + .. autoclass:: TagPolicy :members: :undoc-members: diff --git a/docs/workspace/catalog/external_locations.rst b/docs/workspace/catalog/external_locations.rst index fdf69e38a..caf4e0dca 100644 --- a/docs/workspace/catalog/external_locations.rst +++ b/docs/workspace/catalog/external_locations.rst @@ -32,18 +32,18 @@ credential = w.storage_credentials.create( name=f"sdk-{time.time_ns()}", - aws_iam_role=catalog.AwsIamRoleRequest(role_arn=os.environ["TEST_METASTORE_DATA_ACCESS_ARN"]), + aws_iam_role=catalog.AwsIamRole(role_arn=os.environ["TEST_METASTORE_DATA_ACCESS_ARN"]), ) created = w.external_locations.create( name=f"sdk-{time.time_ns()}", credential_name=credential.name, - url="s3://%s/%s" % (os.environ["TEST_BUCKET"], f"sdk-{time.time_ns()}"), + url=f's3://{os.environ["TEST_BUCKET"]}/sdk-{time.time_ns()}', ) # cleanup - w.storage_credentials.delete(name=credential.name) - w.external_locations.delete(name=created.name) + w.storage_credentials.delete(delete=credential.name) + w.external_locations.delete(delete=created.name) Creates a new external location entry in the metastore. The caller must be a metastore admin or have the **CREATE_EXTERNAL_LOCATION** privilege on both the metastore and the associated storage diff --git a/docs/workspace/catalog/storage_credentials.rst b/docs/workspace/catalog/storage_credentials.rst index 2eacfda5e..07259920c 100644 --- a/docs/workspace/catalog/storage_credentials.rst +++ b/docs/workspace/catalog/storage_credentials.rst @@ -32,11 +32,11 @@ created = w.storage_credentials.create( name=f"sdk-{time.time_ns()}", - aws_iam_role=catalog.AwsIamRole(role_arn=os.environ["TEST_METASTORE_DATA_ACCESS_ARN"]), + aws_iam_role=catalog.AwsIamRoleRequest(role_arn=os.environ["TEST_METASTORE_DATA_ACCESS_ARN"]), ) # cleanup - w.storage_credentials.delete(delete=created.name) + w.storage_credentials.delete(name=created.name) Creates a new storage credential. @@ -98,13 +98,13 @@ created = w.storage_credentials.create( name=f"sdk-{time.time_ns()}", - aws_iam_role=catalog.AwsIamRole(role_arn=os.environ["TEST_METASTORE_DATA_ACCESS_ARN"]), + aws_iam_role=catalog.AwsIamRoleRequest(role_arn=os.environ["TEST_METASTORE_DATA_ACCESS_ARN"]), ) - by_name = w.storage_credentials.get(get=created.name) + by_name = w.storage_credentials.get(name=created.name) # cleanup - w.storage_credentials.delete(delete=created.name) + w.storage_credentials.delete(name=created.name) Gets a storage credential from the metastore. The caller must be a metastore admin, the owner of the storage credential, or have some permission on the storage credential. @@ -123,11 +123,10 @@ .. code-block:: from databricks.sdk import WorkspaceClient - from databricks.sdk.service import catalog w = WorkspaceClient() - all = w.storage_credentials.list(catalog.ListStorageCredentialsRequest()) + all = w.storage_credentials.list() Gets an array of storage credentials (as __StorageCredentialInfo__ objects). The array is limited to only those storage credentials the caller has permission to access. If the caller is a metastore diff --git a/docs/workspace/compute/clusters.rst b/docs/workspace/compute/clusters.rst index db78626ff..8619a5e9a 100644 --- a/docs/workspace/compute/clusters.rst +++ b/docs/workspace/compute/clusters.rst @@ -167,8 +167,7 @@ node_type_id take precedence. :param enable_elastic_disk: bool (optional) Autoscaling Local Storage: when enabled, this cluster will dynamically acquire additional disk space - when its Spark workers are running low on disk space. This feature requires specific AWS permissions - to function correctly - refer to the User Guide for more details. + when its Spark workers are running low on disk space. :param enable_local_disk_encryption: bool (optional) Whether to enable LUKS on cluster VMs' local disks :param gcp_attributes: :class:`GcpAttributes` (optional) @@ -402,8 +401,7 @@ node_type_id take precedence. :param enable_elastic_disk: bool (optional) Autoscaling Local Storage: when enabled, this cluster will dynamically acquire additional disk space - when its Spark workers are running low on disk space. This feature requires specific AWS permissions - to function correctly - refer to the User Guide for more details. + when its Spark workers are running low on disk space. :param enable_local_disk_encryption: bool (optional) Whether to enable LUKS on cluster VMs' local disks :param gcp_attributes: :class:`GcpAttributes` (optional) @@ -647,10 +645,11 @@ .. code-block:: from databricks.sdk import WorkspaceClient + from databricks.sdk.service import compute w = WorkspaceClient() - nodes = w.clusters.list_node_types() + all = w.clusters.list(compute.ListClustersRequest()) Return information about all pinned and active clusters, and all clusters terminated within the last 30 days. Clusters terminated prior to this period are not included. diff --git a/docs/workspace/dashboards/lakeview.rst b/docs/workspace/dashboards/lakeview.rst index e55aeedc8..8048446a1 100644 --- a/docs/workspace/dashboards/lakeview.rst +++ b/docs/workspace/dashboards/lakeview.rst @@ -7,11 +7,19 @@ These APIs provide specific management operations for Lakeview dashboards. Generic resource management can be done with Workspace API (import, export, get-status, list, delete). - .. py:method:: create(dashboard: Dashboard) -> Dashboard + .. py:method:: create(dashboard: Dashboard [, dataset_catalog: Optional[str], dataset_schema: Optional[str]]) -> Dashboard Create a draft dashboard. :param dashboard: :class:`Dashboard` + :param dataset_catalog: str (optional) + Sets the default catalog for all datasets in this dashboard. Does not impact table references that + use fully qualified catalog names (ex: samples.nyctaxi.trips). Leave blank to keep each dataset’s + existing configuration. + :param dataset_schema: str (optional) + Sets the default schema for all datasets in this dashboard. Does not impact table references that + use fully qualified schema names (ex: nyctaxi.trips). Leave blank to keep each dataset’s existing + configuration. :returns: :class:`Dashboard` @@ -222,13 +230,21 @@ - .. py:method:: update(dashboard_id: str, dashboard: Dashboard) -> Dashboard + .. py:method:: update(dashboard_id: str, dashboard: Dashboard [, dataset_catalog: Optional[str], dataset_schema: Optional[str]]) -> Dashboard Update a draft dashboard. :param dashboard_id: str UUID identifying the dashboard. :param dashboard: :class:`Dashboard` + :param dataset_catalog: str (optional) + Sets the default catalog for all datasets in this dashboard. Does not impact table references that + use fully qualified catalog names (ex: samples.nyctaxi.trips). Leave blank to keep each dataset’s + existing configuration. + :param dataset_schema: str (optional) + Sets the default schema for all datasets in this dashboard. Does not impact table references that + use fully qualified schema names (ex: nyctaxi.trips). Leave blank to keep each dataset’s existing + configuration. :returns: :class:`Dashboard` diff --git a/docs/workspace/database/database.rst b/docs/workspace/database/database.rst index 42ba0bb4d..ebfc74ddd 100644 --- a/docs/workspace/database/database.rst +++ b/docs/workspace/database/database.rst @@ -107,11 +107,13 @@ - .. py:method:: delete_synced_database_table(name: str) + .. py:method:: delete_synced_database_table(name: str [, purge_data: Optional[bool]]) Delete a Synced Database Table. :param name: str + :param purge_data: bool (optional) + Optional. When set to true, the actual PostgreSQL table will be dropped from the database. diff --git a/docs/workspace/iam/current_user.rst b/docs/workspace/iam/current_user.rst index 2f95213e2..b2390ce63 100644 --- a/docs/workspace/iam/current_user.rst +++ b/docs/workspace/iam/current_user.rst @@ -17,7 +17,7 @@ w = WorkspaceClient() - me2 = w.current_user.me() + me = w.current_user.me() Get details about the current method caller's identity. diff --git a/docs/workspace/jobs/jobs.rst b/docs/workspace/jobs/jobs.rst index a28fe7aee..c22e872d0 100644 --- a/docs/workspace/jobs/jobs.rst +++ b/docs/workspace/jobs/jobs.rst @@ -523,11 +523,37 @@ .. code-block:: + import os + import time + from databricks.sdk import WorkspaceClient + from databricks.sdk.service import jobs w = WorkspaceClient() - job_list = w.jobs.list(expand_tasks=False) + notebook_path = f"/Users/{w.current_user.me().user_name}/sdk-{time.time_ns()}" + + cluster_id = ( + w.clusters.ensure_cluster_is_running(os.environ["DATABRICKS_CLUSTER_ID"]) and os.environ["DATABRICKS_CLUSTER_ID"] + ) + + created_job = w.jobs.create( + name=f"sdk-{time.time_ns()}", + tasks=[ + jobs.Task( + description="test", + existing_cluster_id=cluster_id, + notebook_task=jobs.NotebookTask(notebook_path=notebook_path), + task_key="test", + timeout_seconds=0, + ) + ], + ) + + run_list = w.jobs.list_runs(job_id=created_job.job_id) + + # cleanup + w.jobs.delete(job_id=created_job.job_id) List jobs. diff --git a/docs/workspace/ml/model_registry.rst b/docs/workspace/ml/model_registry.rst index 601ffd87d..e416ac56b 100644 --- a/docs/workspace/ml/model_registry.rst +++ b/docs/workspace/ml/model_registry.rst @@ -92,7 +92,7 @@ model = w.model_registry.create_model(name=f"sdk-{time.time_ns()}") - created = w.model_registry.create_model_version(name=model.registered_model.name, source="dbfs:/tmp") + mv = w.model_registry.create_model_version(name=model.registered_model.name, source="dbfs:/tmp") Creates a new registered model with the name specified in the request body. Throws `RESOURCE_ALREADY_EXISTS` if a registered model with the given name exists. @@ -122,7 +122,7 @@ model = w.model_registry.create_model(name=f"sdk-{time.time_ns()}") - created = w.model_registry.create_model_version(name=model.registered_model.name, source="dbfs:/tmp") + mv = w.model_registry.create_model_version(name=model.registered_model.name, source="dbfs:/tmp") Creates a model version. @@ -736,14 +736,13 @@ w = WorkspaceClient() - model = w.model_registry.create_model(name=f"sdk-{time.time_ns()}") + created = w.model_registry.create_model(name=f"sdk-{time.time_ns()}") - created = w.model_registry.create_model_version(name=model.registered_model.name, source="dbfs:/tmp") + model = w.model_registry.get_model(name=created.registered_model.name) - w.model_registry.update_model_version( + w.model_registry.update_model( + name=model.registered_model_databricks.name, description=f"sdk-{time.time_ns()}", - name=created.model_version.name, - version=created.model_version.version, ) Updates a registered model. diff --git a/docs/workspace/pipelines/pipelines.rst b/docs/workspace/pipelines/pipelines.rst index e147d5491..b54150ff6 100644 --- a/docs/workspace/pipelines/pipelines.rst +++ b/docs/workspace/pipelines/pipelines.rst @@ -16,6 +16,87 @@ step. You can also enforce data quality with Spark Declarative Pipelines expectations. Expectations allow you to define expected data quality and specify how to handle records that fail those expectations. + .. py:method:: clone(pipeline_id: str [, allow_duplicate_names: Optional[bool], budget_policy_id: Optional[str], catalog: Optional[str], channel: Optional[str], clusters: Optional[List[PipelineCluster]], configuration: Optional[Dict[str, str]], continuous: Optional[bool], deployment: Optional[PipelineDeployment], development: Optional[bool], edition: Optional[str], environment: Optional[PipelinesEnvironment], event_log: Optional[EventLogSpec], expected_last_modified: Optional[int], filters: Optional[Filters], gateway_definition: Optional[IngestionGatewayPipelineDefinition], id: Optional[str], ingestion_definition: Optional[IngestionPipelineDefinition], libraries: Optional[List[PipelineLibrary]], name: Optional[str], notifications: Optional[List[Notifications]], photon: Optional[bool], restart_window: Optional[RestartWindow], root_path: Optional[str], schema: Optional[str], serverless: Optional[bool], storage: Optional[str], tags: Optional[Dict[str, str]], target: Optional[str], trigger: Optional[PipelineTrigger], usage_policy_id: Optional[str]]) -> ClonePipelineResponse + + Creates a new pipeline using Unity Catalog from a pipeline using Hive Metastore. This method returns + the ID of the newly created clone. Additionally, this method starts an update for the newly created + pipeline. + + :param pipeline_id: str + Source pipeline to clone from + :param allow_duplicate_names: bool (optional) + If false, deployment will fail if name conflicts with that of another pipeline. + :param budget_policy_id: str (optional) + Budget policy of this pipeline. + :param catalog: str (optional) + A catalog in Unity Catalog to publish data from this pipeline to. If `target` is specified, tables + in this pipeline are published to a `target` schema inside `catalog` (for example, + `catalog`.`target`.`table`). If `target` is not specified, no data is published to Unity Catalog. + :param channel: str (optional) + DLT Release Channel that specifies which version to use. + :param clusters: List[:class:`PipelineCluster`] (optional) + Cluster settings for this pipeline deployment. + :param configuration: Dict[str,str] (optional) + String-String configuration for this pipeline execution. + :param continuous: bool (optional) + Whether the pipeline is continuous or triggered. This replaces `trigger`. + :param deployment: :class:`PipelineDeployment` (optional) + Deployment type of this pipeline. + :param development: bool (optional) + Whether the pipeline is in Development mode. Defaults to false. + :param edition: str (optional) + Pipeline product edition. + :param environment: :class:`PipelinesEnvironment` (optional) + Environment specification for this pipeline used to install dependencies. + :param event_log: :class:`EventLogSpec` (optional) + Event log configuration for this pipeline + :param expected_last_modified: int (optional) + If present, the last-modified time of the pipeline settings before the clone. If the settings were + modified after that time, then the request will fail with a conflict. + :param filters: :class:`Filters` (optional) + Filters on which Pipeline packages to include in the deployed graph. + :param gateway_definition: :class:`IngestionGatewayPipelineDefinition` (optional) + The definition of a gateway pipeline to support change data capture. + :param id: str (optional) + Unique identifier for this pipeline. + :param ingestion_definition: :class:`IngestionPipelineDefinition` (optional) + The configuration for a managed ingestion pipeline. These settings cannot be used with the + 'libraries', 'schema', 'target', or 'catalog' settings. + :param libraries: List[:class:`PipelineLibrary`] (optional) + Libraries or code needed by this deployment. + :param name: str (optional) + Friendly identifier for this pipeline. + :param notifications: List[:class:`Notifications`] (optional) + List of notification settings for this pipeline. + :param photon: bool (optional) + Whether Photon is enabled for this pipeline. + :param restart_window: :class:`RestartWindow` (optional) + Restart window of this pipeline. + :param root_path: str (optional) + Root path for this pipeline. This is used as the root directory when editing the pipeline in the + Databricks user interface and it is added to sys.path when executing Python sources during pipeline + execution. + :param schema: str (optional) + The default schema (database) where tables are read from or published to. + :param serverless: bool (optional) + Whether serverless compute is enabled for this pipeline. + :param storage: str (optional) + DBFS root directory for storing checkpoints and tables. + :param tags: Dict[str,str] (optional) + A map of tags associated with the pipeline. These are forwarded to the cluster as cluster tags, and + are therefore subject to the same limitations. A maximum of 25 tags can be added to the pipeline. + :param target: str (optional) + Target schema (database) to add tables in this pipeline to. Exactly one of `schema` or `target` must + be specified. To publish to Unity Catalog, also specify `catalog`. This legacy field is deprecated + for pipeline creation in favor of the `schema` field. + :param trigger: :class:`PipelineTrigger` (optional) + Which pipeline trigger to use. Deprecated: Use `continuous` instead. + :param usage_policy_id: str (optional) + Usage policy of this pipeline. + + :returns: :class:`ClonePipelineResponse` + + .. py:method:: create( [, allow_duplicate_names: Optional[bool], budget_policy_id: Optional[str], catalog: Optional[str], channel: Optional[str], clusters: Optional[List[PipelineCluster]], configuration: Optional[Dict[str, str]], continuous: Optional[bool], deployment: Optional[PipelineDeployment], development: Optional[bool], dry_run: Optional[bool], edition: Optional[str], environment: Optional[PipelinesEnvironment], event_log: Optional[EventLogSpec], filters: Optional[Filters], gateway_definition: Optional[IngestionGatewayPipelineDefinition], id: Optional[str], ingestion_definition: Optional[IngestionPipelineDefinition], libraries: Optional[List[PipelineLibrary]], name: Optional[str], notifications: Optional[List[Notifications]], photon: Optional[bool], restart_window: Optional[RestartWindow], root_path: Optional[str], run_as: Optional[RunAs], schema: Optional[str], serverless: Optional[bool], storage: Optional[str], tags: Optional[Dict[str, str]], target: Optional[str], trigger: Optional[PipelineTrigger], usage_policy_id: Optional[str]]) -> CreatePipelineResponse diff --git a/docs/workspace/sharing/providers.rst b/docs/workspace/sharing/providers.rst index 1a7c88de9..fd81e1b24 100644 --- a/docs/workspace/sharing/providers.rst +++ b/docs/workspace/sharing/providers.rst @@ -101,25 +101,12 @@ .. code-block:: - import time - from databricks.sdk import WorkspaceClient + from databricks.sdk.service import sharing w = WorkspaceClient() - public_share_recipient = """{ - "shareCredentialsVersion":1, - "bearerToken":"dapiabcdefghijklmonpqrstuvwxyz", - "endpoint":"https://sharing.delta.io/delta-sharing/" - } - """ - - created = w.providers.create(name=f"sdk-{time.time_ns()}", recipient_profile_str=public_share_recipient) - - shares = w.providers.list_shares(name=created.name) - - # cleanup - w.providers.delete(name=created.name) + all = w.providers.list(sharing.ListProvidersRequest()) Gets an array of available authentication providers. The caller must either be a metastore admin or the owner of the providers. Providers not owned by the caller are not included in the response. There diff --git a/docs/workspace/sql/dbsql_permissions.rst b/docs/workspace/sql/dbsql_permissions.rst index c05c82012..77b5bb9c5 100644 --- a/docs/workspace/sql/dbsql_permissions.rst +++ b/docs/workspace/sql/dbsql_permissions.rst @@ -1,5 +1,5 @@ -``w.dbsql_permissions``: ACL / Permissions -========================================== +``w.dbsql_permissions``: Permissions (legacy) +============================================= .. currentmodule:: databricks.sdk.service.sql .. py:class:: DbsqlPermissionsAPI diff --git a/docs/workspace/tags/index.rst b/docs/workspace/tags/index.rst index 5489c384d..69bc5cf8d 100644 --- a/docs/workspace/tags/index.rst +++ b/docs/workspace/tags/index.rst @@ -7,4 +7,5 @@ Manage tag policies and tag assignments on workspace objects .. toctree:: :maxdepth: 1 - tag_policies \ No newline at end of file + tag_policies + workspace_entity_tag_assignments \ No newline at end of file diff --git a/docs/workspace/tags/workspace_entity_tag_assignments.rst b/docs/workspace/tags/workspace_entity_tag_assignments.rst new file mode 100644 index 000000000..1629028ba --- /dev/null +++ b/docs/workspace/tags/workspace_entity_tag_assignments.rst @@ -0,0 +1,85 @@ +``w.workspace_entity_tag_assignments``: Tag Assignments +======================================================= +.. currentmodule:: databricks.sdk.service.tags + +.. py:class:: WorkspaceEntityTagAssignmentsAPI + + Manage tag assignments on workspace-scoped objects. + + .. py:method:: create_tag_assignment(tag_assignment: TagAssignment) -> TagAssignment + + Create a tag assignment + + :param tag_assignment: :class:`TagAssignment` + + :returns: :class:`TagAssignment` + + + .. py:method:: delete_tag_assignment(entity_type: str, entity_id: str, tag_key: str) + + Delete a tag assignment + + :param entity_type: str + The type of entity to which the tag is assigned. Allowed values are dashboards, geniespaces + :param entity_id: str + The identifier of the entity to which the tag is assigned + :param tag_key: str + The key of the tag. The characters , . : / - = and leading/trailing spaces are not allowed + + + + + .. py:method:: get_tag_assignment(entity_type: str, entity_id: str, tag_key: str) -> TagAssignment + + Get a tag assignment + + :param entity_type: str + The type of entity to which the tag is assigned. Allowed values are dashboards, geniespaces + :param entity_id: str + The identifier of the entity to which the tag is assigned + :param tag_key: str + The key of the tag. The characters , . : / - = and leading/trailing spaces are not allowed + + :returns: :class:`TagAssignment` + + + .. py:method:: list_tag_assignments(entity_type: str, entity_id: str [, page_size: Optional[int], page_token: Optional[str]]) -> Iterator[TagAssignment] + + List the tag assignments for an entity + + :param entity_type: str + The type of entity to which the tag is assigned. Allowed values are dashboards, geniespaces + :param entity_id: str + The identifier of the entity to which the tag is assigned + :param page_size: int (optional) + Optional. Maximum number of tag assignments to return in a single page + :param page_token: str (optional) + Pagination token to go to the next page of tag assignments. Requests first page if absent. + + :returns: Iterator over :class:`TagAssignment` + + + .. py:method:: update_tag_assignment(entity_type: str, entity_id: str, tag_key: str, tag_assignment: TagAssignment, update_mask: str) -> TagAssignment + + Update a tag assignment + + :param entity_type: str + The type of entity to which the tag is assigned. Allowed values are dashboards, geniespaces + :param entity_id: str + The identifier of the entity to which the tag is assigned + :param tag_key: str + The key of the tag. The characters , . : / - = and leading/trailing spaces are not allowed + :param tag_assignment: :class:`TagAssignment` + :param update_mask: str + 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`). Specification of elements in sequence or map fields is not allowed, as only + the entire collection field can be specified. Field names must exactly match the resource field + names. + + A field mask of `*` indicates full replacement. It’s recommended to always explicitly list the + fields being updated and avoid using `*` wildcards, as it can lead to unintended results if the API + changes in the future. + + :returns: :class:`TagAssignment` + \ No newline at end of file diff --git a/docs/workspace/workspace/workspace.rst b/docs/workspace/workspace/workspace.rst index aaccfb1c4..6931faabd 100644 --- a/docs/workspace/workspace/workspace.rst +++ b/docs/workspace/workspace/workspace.rst @@ -179,11 +179,16 @@ notebook_path = f"/Users/{w.current_user.me().user_name}/sdk-{time.time_ns()}" w.workspace.import_( - content=base64.b64encode(("CREATE LIVE TABLE dlt_sample AS SELECT 1").encode()).decode(), - format=workspace.ImportFormat.SOURCE, - language=workspace.Language.SQL, - overwrite=true_, path=notebook_path, + overwrite=true_, + format=workspace.ImportFormat.SOURCE, + language=workspace.Language.PYTHON, + content=base64.b64encode( + ( + """print(1) + """ + ).encode() + ).decode(), ) Imports a workspace object (for example, a notebook or file) or the contents of an entire directory.