# Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT. from __future__ import annotations import logging import random import time from dataclasses import dataclass from datetime import timedelta from enum import Enum from typing import Any, Callable, Dict, Iterator, List, Optional from google.protobuf.timestamp_pb2 import Timestamp from databricks.sdk.client_types import HostType from databricks.sdk.common import lro from databricks.sdk.common.types.fieldmask import FieldMask from databricks.sdk.retries import RetryError, poll from databricks.sdk.service._internal import (Wait, _enum, _from_dict, _repeated_dict, _timestamp) from ..errors import OperationFailed _LOG = logging.getLogger("databricks.sdk") # all definitions in this file are in alphabetical order @dataclass class App: name: str """The name of the app. The name must contain only lowercase alphanumeric characters and hyphens. It must be unique within the workspace.""" active_deployment: Optional[AppDeployment] = None """The active deployment of the app. A deployment is considered active when it has been deployed to the app compute.""" app_status: Optional[ApplicationStatus] = None budget_policy_id: Optional[str] = None compute_size: Optional[ComputeSize] = None compute_status: Optional[ComputeStatus] = None create_time: Optional[str] = None """The creation time of the app. Formatted timestamp in ISO 6801.""" creator: Optional[str] = None """The email of the user that created the app.""" default_source_code_path: Optional[str] = None """The default workspace file system path of the source code from which app deployment are created. This field tracks the workspace source code path of the last active deployment.""" description: Optional[str] = None """The description of the app.""" effective_budget_policy_id: Optional[str] = None effective_usage_policy_id: Optional[str] = None effective_user_api_scopes: Optional[List[str]] = None """The effective api scopes granted to the user access token.""" git_repository: Optional[GitRepository] = None """Git repository configuration for app deployments. When specified, deployments can reference code from this repository by providing only the git reference (branch, tag, or commit).""" id: Optional[str] = None """The unique identifier of the app.""" oauth2_app_client_id: Optional[str] = None oauth2_app_integration_id: Optional[str] = None pending_deployment: Optional[AppDeployment] = None """The pending deployment of the app. A deployment is considered pending when it is being prepared for deployment to the app compute.""" resources: Optional[List[AppResource]] = None """Resources for the app.""" service_principal_client_id: Optional[str] = None service_principal_id: Optional[int] = None service_principal_name: Optional[str] = None space: Optional[str] = None """Name of the space this app belongs to.""" update_time: Optional[str] = None """The update time of the app. Formatted timestamp in ISO 6801.""" updater: Optional[str] = None """The email of the user that last updated the app.""" url: Optional[str] = None """The URL of the app once it is deployed.""" usage_policy_id: Optional[str] = None user_api_scopes: Optional[List[str]] = None def as_dict(self) -> dict: """Serializes the App into a dictionary suitable for use as a JSON request body.""" body = {} if self.active_deployment: body["active_deployment"] = self.active_deployment.as_dict() if self.app_status: body["app_status"] = self.app_status.as_dict() if self.budget_policy_id is not None: body["budget_policy_id"] = self.budget_policy_id if self.compute_size is not None: body["compute_size"] = self.compute_size.value if self.compute_status: body["compute_status"] = self.compute_status.as_dict() if self.create_time is not None: body["create_time"] = self.create_time if self.creator is not None: body["creator"] = self.creator if self.default_source_code_path is not None: body["default_source_code_path"] = self.default_source_code_path if self.description is not None: body["description"] = self.description if self.effective_budget_policy_id is not None: body["effective_budget_policy_id"] = self.effective_budget_policy_id if self.effective_usage_policy_id is not None: body["effective_usage_policy_id"] = self.effective_usage_policy_id if self.effective_user_api_scopes: body["effective_user_api_scopes"] = [v for v in self.effective_user_api_scopes] if self.git_repository: body["git_repository"] = self.git_repository.as_dict() if self.id is not None: body["id"] = self.id if self.name is not None: body["name"] = self.name if self.oauth2_app_client_id is not None: body["oauth2_app_client_id"] = self.oauth2_app_client_id if self.oauth2_app_integration_id is not None: body["oauth2_app_integration_id"] = self.oauth2_app_integration_id if self.pending_deployment: body["pending_deployment"] = self.pending_deployment.as_dict() if self.resources: body["resources"] = [v.as_dict() for v in self.resources] if self.service_principal_client_id is not None: body["service_principal_client_id"] = self.service_principal_client_id if self.service_principal_id is not None: body["service_principal_id"] = self.service_principal_id if self.service_principal_name is not None: body["service_principal_name"] = self.service_principal_name if self.space is not None: body["space"] = self.space if self.update_time is not None: body["update_time"] = self.update_time if self.updater is not None: body["updater"] = self.updater if self.url is not None: body["url"] = self.url if self.usage_policy_id is not None: body["usage_policy_id"] = self.usage_policy_id if self.user_api_scopes: body["user_api_scopes"] = [v for v in self.user_api_scopes] return body def as_shallow_dict(self) -> dict: """Serializes the App into a shallow dictionary of its immediate attributes.""" body = {} if self.active_deployment: body["active_deployment"] = self.active_deployment if self.app_status: body["app_status"] = self.app_status if self.budget_policy_id is not None: body["budget_policy_id"] = self.budget_policy_id if self.compute_size is not None: body["compute_size"] = self.compute_size if self.compute_status: body["compute_status"] = self.compute_status if self.create_time is not None: body["create_time"] = self.create_time if self.creator is not None: body["creator"] = self.creator if self.default_source_code_path is not None: body["default_source_code_path"] = self.default_source_code_path if self.description is not None: body["description"] = self.description if self.effective_budget_policy_id is not None: body["effective_budget_policy_id"] = self.effective_budget_policy_id if self.effective_usage_policy_id is not None: body["effective_usage_policy_id"] = self.effective_usage_policy_id if self.effective_user_api_scopes: body["effective_user_api_scopes"] = self.effective_user_api_scopes if self.git_repository: body["git_repository"] = self.git_repository if self.id is not None: body["id"] = self.id if self.name is not None: body["name"] = self.name if self.oauth2_app_client_id is not None: body["oauth2_app_client_id"] = self.oauth2_app_client_id if self.oauth2_app_integration_id is not None: body["oauth2_app_integration_id"] = self.oauth2_app_integration_id if self.pending_deployment: body["pending_deployment"] = self.pending_deployment if self.resources: body["resources"] = self.resources if self.service_principal_client_id is not None: body["service_principal_client_id"] = self.service_principal_client_id if self.service_principal_id is not None: body["service_principal_id"] = self.service_principal_id if self.service_principal_name is not None: body["service_principal_name"] = self.service_principal_name if self.space is not None: body["space"] = self.space if self.update_time is not None: body["update_time"] = self.update_time if self.updater is not None: body["updater"] = self.updater if self.url is not None: body["url"] = self.url if self.usage_policy_id is not None: body["usage_policy_id"] = self.usage_policy_id if self.user_api_scopes: body["user_api_scopes"] = self.user_api_scopes return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> App: """Deserializes the App from a dictionary.""" return cls( active_deployment=_from_dict(d, "active_deployment", AppDeployment), app_status=_from_dict(d, "app_status", ApplicationStatus), budget_policy_id=d.get("budget_policy_id", None), compute_size=_enum(d, "compute_size", ComputeSize), compute_status=_from_dict(d, "compute_status", ComputeStatus), create_time=d.get("create_time", None), creator=d.get("creator", None), default_source_code_path=d.get("default_source_code_path", None), description=d.get("description", None), effective_budget_policy_id=d.get("effective_budget_policy_id", None), effective_usage_policy_id=d.get("effective_usage_policy_id", None), effective_user_api_scopes=d.get("effective_user_api_scopes", None), git_repository=_from_dict(d, "git_repository", GitRepository), id=d.get("id", None), name=d.get("name", None), oauth2_app_client_id=d.get("oauth2_app_client_id", None), oauth2_app_integration_id=d.get("oauth2_app_integration_id", None), pending_deployment=_from_dict(d, "pending_deployment", AppDeployment), resources=_repeated_dict(d, "resources", AppResource), service_principal_client_id=d.get("service_principal_client_id", None), service_principal_id=d.get("service_principal_id", None), service_principal_name=d.get("service_principal_name", None), space=d.get("space", None), update_time=d.get("update_time", None), updater=d.get("updater", None), url=d.get("url", None), usage_policy_id=d.get("usage_policy_id", None), user_api_scopes=d.get("user_api_scopes", None), ) @dataclass class AppAccessControlRequest: group_name: Optional[str] = None """name of the group""" permission_level: Optional[AppPermissionLevel] = None service_principal_name: Optional[str] = None """application ID of a service principal""" user_name: Optional[str] = None """name of the user""" def as_dict(self) -> dict: """Serializes the AppAccessControlRequest into a dictionary suitable for use as a JSON request body.""" body = {} if self.group_name is not None: body["group_name"] = self.group_name if self.permission_level is not None: body["permission_level"] = self.permission_level.value if self.service_principal_name is not None: body["service_principal_name"] = self.service_principal_name if self.user_name is not None: body["user_name"] = self.user_name return body def as_shallow_dict(self) -> dict: """Serializes the AppAccessControlRequest into a shallow dictionary of its immediate attributes.""" body = {} if self.group_name is not None: body["group_name"] = self.group_name if self.permission_level is not None: body["permission_level"] = self.permission_level if self.service_principal_name is not None: body["service_principal_name"] = self.service_principal_name if self.user_name is not None: body["user_name"] = self.user_name return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppAccessControlRequest: """Deserializes the AppAccessControlRequest from a dictionary.""" return cls( group_name=d.get("group_name", None), permission_level=_enum(d, "permission_level", AppPermissionLevel), service_principal_name=d.get("service_principal_name", None), user_name=d.get("user_name", None), ) @dataclass class AppAccessControlResponse: all_permissions: Optional[List[AppPermission]] = None """All permissions.""" display_name: Optional[str] = None """Display name of the user or service principal.""" group_name: Optional[str] = None """name of the group""" service_principal_name: Optional[str] = None """Name of the service principal.""" user_name: Optional[str] = None """name of the user""" def as_dict(self) -> dict: """Serializes the AppAccessControlResponse into a dictionary suitable for use as a JSON request body.""" body = {} if self.all_permissions: body["all_permissions"] = [v.as_dict() for v in self.all_permissions] if self.display_name is not None: body["display_name"] = self.display_name if self.group_name is not None: body["group_name"] = self.group_name if self.service_principal_name is not None: body["service_principal_name"] = self.service_principal_name if self.user_name is not None: body["user_name"] = self.user_name return body def as_shallow_dict(self) -> dict: """Serializes the AppAccessControlResponse into a shallow dictionary of its immediate attributes.""" body = {} if self.all_permissions: body["all_permissions"] = self.all_permissions if self.display_name is not None: body["display_name"] = self.display_name if self.group_name is not None: body["group_name"] = self.group_name if self.service_principal_name is not None: body["service_principal_name"] = self.service_principal_name if self.user_name is not None: body["user_name"] = self.user_name return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppAccessControlResponse: """Deserializes the AppAccessControlResponse from a dictionary.""" return cls( all_permissions=_repeated_dict(d, "all_permissions", AppPermission), display_name=d.get("display_name", None), group_name=d.get("group_name", None), service_principal_name=d.get("service_principal_name", None), user_name=d.get("user_name", None), ) @dataclass class AppDeployment: command: Optional[List[str]] = None """The command with which to run the app. This will override the command specified in the app.yaml file.""" create_time: Optional[str] = None """The creation time of the deployment. Formatted timestamp in ISO 6801.""" creator: Optional[str] = None """The email of the user creates the deployment.""" deployment_artifacts: Optional[AppDeploymentArtifacts] = None """The deployment artifacts for an app.""" deployment_id: Optional[str] = None """The unique id of the deployment.""" env_vars: Optional[List[EnvVar]] = None """The environment variables to set in the app runtime environment. This will override the environment variables specified in the app.yaml file.""" git_source: Optional[GitSource] = None """Git repository to use as the source for the app deployment.""" mode: Optional[AppDeploymentMode] = None """The mode of which the deployment will manage the source code.""" source_code_path: Optional[str] = None """The workspace file system path of the source code used to create the app deployment. This is different from `deployment_artifacts.source_code_path`, which is the path used by the deployed app. The former refers to the original source code location of the app in the workspace during deployment creation, whereas the latter provides a system generated stable snapshotted source code path used by the deployment.""" status: Optional[AppDeploymentStatus] = None """Status and status message of the deployment""" update_time: Optional[str] = None """The update time of the deployment. Formatted timestamp in ISO 6801.""" def as_dict(self) -> dict: """Serializes the AppDeployment into a dictionary suitable for use as a JSON request body.""" body = {} if self.command: body["command"] = [v for v in self.command] if self.create_time is not None: body["create_time"] = self.create_time if self.creator is not None: body["creator"] = self.creator if self.deployment_artifacts: body["deployment_artifacts"] = self.deployment_artifacts.as_dict() if self.deployment_id is not None: body["deployment_id"] = self.deployment_id if self.env_vars: body["env_vars"] = [v.as_dict() for v in self.env_vars] if self.git_source: body["git_source"] = self.git_source.as_dict() if self.mode is not None: body["mode"] = self.mode.value if self.source_code_path is not None: body["source_code_path"] = self.source_code_path if self.status: body["status"] = self.status.as_dict() if self.update_time is not None: body["update_time"] = self.update_time return body def as_shallow_dict(self) -> dict: """Serializes the AppDeployment into a shallow dictionary of its immediate attributes.""" body = {} if self.command: body["command"] = self.command if self.create_time is not None: body["create_time"] = self.create_time if self.creator is not None: body["creator"] = self.creator if self.deployment_artifacts: body["deployment_artifacts"] = self.deployment_artifacts if self.deployment_id is not None: body["deployment_id"] = self.deployment_id if self.env_vars: body["env_vars"] = self.env_vars if self.git_source: body["git_source"] = self.git_source if self.mode is not None: body["mode"] = self.mode if self.source_code_path is not None: body["source_code_path"] = self.source_code_path if self.status: body["status"] = self.status if self.update_time is not None: body["update_time"] = self.update_time return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppDeployment: """Deserializes the AppDeployment from a dictionary.""" return cls( command=d.get("command", None), create_time=d.get("create_time", None), creator=d.get("creator", None), deployment_artifacts=_from_dict(d, "deployment_artifacts", AppDeploymentArtifacts), deployment_id=d.get("deployment_id", None), env_vars=_repeated_dict(d, "env_vars", EnvVar), git_source=_from_dict(d, "git_source", GitSource), mode=_enum(d, "mode", AppDeploymentMode), source_code_path=d.get("source_code_path", None), status=_from_dict(d, "status", AppDeploymentStatus), update_time=d.get("update_time", None), ) @dataclass class AppDeploymentArtifacts: source_code_path: Optional[str] = None """The snapshotted workspace file system path of the source code loaded by the deployed app.""" def as_dict(self) -> dict: """Serializes the AppDeploymentArtifacts into a dictionary suitable for use as a JSON request body.""" body = {} if self.source_code_path is not None: body["source_code_path"] = self.source_code_path return body def as_shallow_dict(self) -> dict: """Serializes the AppDeploymentArtifacts into a shallow dictionary of its immediate attributes.""" body = {} if self.source_code_path is not None: body["source_code_path"] = self.source_code_path return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppDeploymentArtifacts: """Deserializes the AppDeploymentArtifacts from a dictionary.""" return cls(source_code_path=d.get("source_code_path", None)) class AppDeploymentMode(Enum): AUTO_SYNC = "AUTO_SYNC" SNAPSHOT = "SNAPSHOT" class AppDeploymentState(Enum): CANCELLED = "CANCELLED" FAILED = "FAILED" IN_PROGRESS = "IN_PROGRESS" SUCCEEDED = "SUCCEEDED" @dataclass class AppDeploymentStatus: message: Optional[str] = None """Message corresponding with the deployment state.""" state: Optional[AppDeploymentState] = None """State of the deployment.""" def as_dict(self) -> dict: """Serializes the AppDeploymentStatus into a dictionary suitable for use as a JSON request body.""" body = {} if self.message is not None: body["message"] = self.message if self.state is not None: body["state"] = self.state.value return body def as_shallow_dict(self) -> dict: """Serializes the AppDeploymentStatus into a shallow dictionary of its immediate attributes.""" body = {} if self.message is not None: body["message"] = self.message if self.state is not None: body["state"] = self.state return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppDeploymentStatus: """Deserializes the AppDeploymentStatus from a dictionary.""" return cls(message=d.get("message", None), state=_enum(d, "state", AppDeploymentState)) @dataclass class AppManifest: """App manifest definition""" version: int """The manifest schema version, for now only 1 is allowed""" name: str """Name of the app defined by manifest author / publisher""" description: Optional[str] = None """Description of the app defined by manifest author / publisher""" resource_specs: Optional[List[AppManifestAppResourceSpec]] = None def as_dict(self) -> dict: """Serializes the AppManifest into a dictionary suitable for use as a JSON request body.""" body = {} if self.description is not None: body["description"] = self.description if self.name is not None: body["name"] = self.name if self.resource_specs: body["resource_specs"] = [v.as_dict() for v in self.resource_specs] if self.version is not None: body["version"] = self.version return body def as_shallow_dict(self) -> dict: """Serializes the AppManifest into a shallow dictionary of its immediate attributes.""" body = {} if self.description is not None: body["description"] = self.description if self.name is not None: body["name"] = self.name if self.resource_specs: body["resource_specs"] = self.resource_specs if self.version is not None: body["version"] = self.version return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppManifest: """Deserializes the AppManifest from a dictionary.""" return cls( description=d.get("description", None), name=d.get("name", None), resource_specs=_repeated_dict(d, "resource_specs", AppManifestAppResourceSpec), version=d.get("version", None), ) @dataclass class AppManifestAppResourceExperimentSpec: permission: AppManifestAppResourceExperimentSpecExperimentPermission def as_dict(self) -> dict: """Serializes the AppManifestAppResourceExperimentSpec into a dictionary suitable for use as a JSON request body.""" body = {} if self.permission is not None: body["permission"] = self.permission.value return body def as_shallow_dict(self) -> dict: """Serializes the AppManifestAppResourceExperimentSpec into a shallow dictionary of its immediate attributes.""" body = {} if self.permission is not None: body["permission"] = self.permission return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppManifestAppResourceExperimentSpec: """Deserializes the AppManifestAppResourceExperimentSpec from a dictionary.""" return cls(permission=_enum(d, "permission", AppManifestAppResourceExperimentSpecExperimentPermission)) class AppManifestAppResourceExperimentSpecExperimentPermission(Enum): CAN_EDIT = "CAN_EDIT" CAN_MANAGE = "CAN_MANAGE" CAN_READ = "CAN_READ" @dataclass class AppManifestAppResourceJobSpec: permission: AppManifestAppResourceJobSpecJobPermission """Permissions to grant on the Job. Supported permissions are: "CAN_MANAGE", "IS_OWNER", "CAN_MANAGE_RUN", "CAN_VIEW".""" def as_dict(self) -> dict: """Serializes the AppManifestAppResourceJobSpec into a dictionary suitable for use as a JSON request body.""" body = {} if self.permission is not None: body["permission"] = self.permission.value return body def as_shallow_dict(self) -> dict: """Serializes the AppManifestAppResourceJobSpec into a shallow dictionary of its immediate attributes.""" body = {} if self.permission is not None: body["permission"] = self.permission return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppManifestAppResourceJobSpec: """Deserializes the AppManifestAppResourceJobSpec from a dictionary.""" return cls(permission=_enum(d, "permission", AppManifestAppResourceJobSpecJobPermission)) class AppManifestAppResourceJobSpecJobPermission(Enum): CAN_MANAGE = "CAN_MANAGE" CAN_MANAGE_RUN = "CAN_MANAGE_RUN" CAN_VIEW = "CAN_VIEW" IS_OWNER = "IS_OWNER" @dataclass class AppManifestAppResourceSecretSpec: permission: AppManifestAppResourceSecretSpecSecretPermission """Permission to grant on the secret scope. For secrets, only one permission is allowed. Permission must be one of: "READ", "WRITE", "MANAGE".""" def as_dict(self) -> dict: """Serializes the AppManifestAppResourceSecretSpec into a dictionary suitable for use as a JSON request body.""" body = {} if self.permission is not None: body["permission"] = self.permission.value return body def as_shallow_dict(self) -> dict: """Serializes the AppManifestAppResourceSecretSpec into a shallow dictionary of its immediate attributes.""" body = {} if self.permission is not None: body["permission"] = self.permission return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppManifestAppResourceSecretSpec: """Deserializes the AppManifestAppResourceSecretSpec from a dictionary.""" return cls(permission=_enum(d, "permission", AppManifestAppResourceSecretSpecSecretPermission)) class AppManifestAppResourceSecretSpecSecretPermission(Enum): """Permission to grant on the secret scope. Supported permissions are: "READ", "WRITE", "MANAGE".""" MANAGE = "MANAGE" READ = "READ" WRITE = "WRITE" @dataclass class AppManifestAppResourceServingEndpointSpec: permission: AppManifestAppResourceServingEndpointSpecServingEndpointPermission """Permission to grant on the serving endpoint. Supported permissions are: "CAN_MANAGE", "CAN_QUERY", "CAN_VIEW".""" def as_dict(self) -> dict: """Serializes the AppManifestAppResourceServingEndpointSpec into a dictionary suitable for use as a JSON request body.""" body = {} if self.permission is not None: body["permission"] = self.permission.value return body def as_shallow_dict(self) -> dict: """Serializes the AppManifestAppResourceServingEndpointSpec into a shallow dictionary of its immediate attributes.""" body = {} if self.permission is not None: body["permission"] = self.permission return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppManifestAppResourceServingEndpointSpec: """Deserializes the AppManifestAppResourceServingEndpointSpec from a dictionary.""" return cls( permission=_enum(d, "permission", AppManifestAppResourceServingEndpointSpecServingEndpointPermission) ) class AppManifestAppResourceServingEndpointSpecServingEndpointPermission(Enum): CAN_MANAGE = "CAN_MANAGE" CAN_QUERY = "CAN_QUERY" CAN_VIEW = "CAN_VIEW" @dataclass class AppManifestAppResourceSpec: """AppResource related fields are copied from app.proto but excludes resource identifiers (e.g. name, id, key, scope, etc.)""" name: str """Name of the App Resource.""" description: Optional[str] = None """Description of the App Resource.""" experiment_spec: Optional[AppManifestAppResourceExperimentSpec] = None job_spec: Optional[AppManifestAppResourceJobSpec] = None secret_spec: Optional[AppManifestAppResourceSecretSpec] = None serving_endpoint_spec: Optional[AppManifestAppResourceServingEndpointSpec] = None sql_warehouse_spec: Optional[AppManifestAppResourceSqlWarehouseSpec] = None uc_securable_spec: Optional[AppManifestAppResourceUcSecurableSpec] = None def as_dict(self) -> dict: """Serializes the AppManifestAppResourceSpec into a dictionary suitable for use as a JSON request body.""" body = {} if self.description is not None: body["description"] = self.description if self.experiment_spec: body["experiment_spec"] = self.experiment_spec.as_dict() if self.job_spec: body["job_spec"] = self.job_spec.as_dict() if self.name is not None: body["name"] = self.name if self.secret_spec: body["secret_spec"] = self.secret_spec.as_dict() if self.serving_endpoint_spec: body["serving_endpoint_spec"] = self.serving_endpoint_spec.as_dict() if self.sql_warehouse_spec: body["sql_warehouse_spec"] = self.sql_warehouse_spec.as_dict() if self.uc_securable_spec: body["uc_securable_spec"] = self.uc_securable_spec.as_dict() return body def as_shallow_dict(self) -> dict: """Serializes the AppManifestAppResourceSpec into a shallow dictionary of its immediate attributes.""" body = {} if self.description is not None: body["description"] = self.description if self.experiment_spec: body["experiment_spec"] = self.experiment_spec if self.job_spec: body["job_spec"] = self.job_spec if self.name is not None: body["name"] = self.name if self.secret_spec: body["secret_spec"] = self.secret_spec if self.serving_endpoint_spec: body["serving_endpoint_spec"] = self.serving_endpoint_spec if self.sql_warehouse_spec: body["sql_warehouse_spec"] = self.sql_warehouse_spec if self.uc_securable_spec: body["uc_securable_spec"] = self.uc_securable_spec return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppManifestAppResourceSpec: """Deserializes the AppManifestAppResourceSpec from a dictionary.""" return cls( description=d.get("description", None), experiment_spec=_from_dict(d, "experiment_spec", AppManifestAppResourceExperimentSpec), job_spec=_from_dict(d, "job_spec", AppManifestAppResourceJobSpec), name=d.get("name", None), secret_spec=_from_dict(d, "secret_spec", AppManifestAppResourceSecretSpec), serving_endpoint_spec=_from_dict(d, "serving_endpoint_spec", AppManifestAppResourceServingEndpointSpec), sql_warehouse_spec=_from_dict(d, "sql_warehouse_spec", AppManifestAppResourceSqlWarehouseSpec), uc_securable_spec=_from_dict(d, "uc_securable_spec", AppManifestAppResourceUcSecurableSpec), ) @dataclass class AppManifestAppResourceSqlWarehouseSpec: permission: AppManifestAppResourceSqlWarehouseSpecSqlWarehousePermission """Permission to grant on the SQL warehouse. Supported permissions are: "CAN_MANAGE", "CAN_USE", "IS_OWNER".""" def as_dict(self) -> dict: """Serializes the AppManifestAppResourceSqlWarehouseSpec into a dictionary suitable for use as a JSON request body.""" body = {} if self.permission is not None: body["permission"] = self.permission.value return body def as_shallow_dict(self) -> dict: """Serializes the AppManifestAppResourceSqlWarehouseSpec into a shallow dictionary of its immediate attributes.""" body = {} if self.permission is not None: body["permission"] = self.permission return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppManifestAppResourceSqlWarehouseSpec: """Deserializes the AppManifestAppResourceSqlWarehouseSpec from a dictionary.""" return cls(permission=_enum(d, "permission", AppManifestAppResourceSqlWarehouseSpecSqlWarehousePermission)) class AppManifestAppResourceSqlWarehouseSpecSqlWarehousePermission(Enum): CAN_MANAGE = "CAN_MANAGE" CAN_USE = "CAN_USE" IS_OWNER = "IS_OWNER" @dataclass class AppManifestAppResourceUcSecurableSpec: securable_type: AppManifestAppResourceUcSecurableSpecUcSecurableType permission: AppManifestAppResourceUcSecurableSpecUcSecurablePermission def as_dict(self) -> dict: """Serializes the AppManifestAppResourceUcSecurableSpec into a dictionary suitable for use as a JSON request body.""" body = {} if self.permission is not None: body["permission"] = self.permission.value if self.securable_type is not None: body["securable_type"] = self.securable_type.value return body def as_shallow_dict(self) -> dict: """Serializes the AppManifestAppResourceUcSecurableSpec into a shallow dictionary of its immediate attributes.""" body = {} if self.permission is not None: body["permission"] = self.permission if self.securable_type is not None: body["securable_type"] = self.securable_type return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppManifestAppResourceUcSecurableSpec: """Deserializes the AppManifestAppResourceUcSecurableSpec from a dictionary.""" return cls( permission=_enum(d, "permission", AppManifestAppResourceUcSecurableSpecUcSecurablePermission), securable_type=_enum(d, "securable_type", AppManifestAppResourceUcSecurableSpecUcSecurableType), ) class AppManifestAppResourceUcSecurableSpecUcSecurablePermission(Enum): EXECUTE = "EXECUTE" MANAGE = "MANAGE" READ_VOLUME = "READ_VOLUME" SELECT = "SELECT" USE_CONNECTION = "USE_CONNECTION" WRITE_VOLUME = "WRITE_VOLUME" class AppManifestAppResourceUcSecurableSpecUcSecurableType(Enum): CONNECTION = "CONNECTION" FUNCTION = "FUNCTION" TABLE = "TABLE" VOLUME = "VOLUME" @dataclass class AppPermission: inherited: Optional[bool] = None inherited_from_object: Optional[List[str]] = None permission_level: Optional[AppPermissionLevel] = None def as_dict(self) -> dict: """Serializes the AppPermission into a dictionary suitable for use as a JSON request body.""" body = {} if self.inherited is not None: body["inherited"] = self.inherited if self.inherited_from_object: body["inherited_from_object"] = [v for v in self.inherited_from_object] if self.permission_level is not None: body["permission_level"] = self.permission_level.value return body def as_shallow_dict(self) -> dict: """Serializes the AppPermission into a shallow dictionary of its immediate attributes.""" body = {} if self.inherited is not None: body["inherited"] = self.inherited if self.inherited_from_object: body["inherited_from_object"] = self.inherited_from_object if self.permission_level is not None: body["permission_level"] = self.permission_level return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppPermission: """Deserializes the AppPermission from a dictionary.""" return cls( inherited=d.get("inherited", None), inherited_from_object=d.get("inherited_from_object", None), permission_level=_enum(d, "permission_level", AppPermissionLevel), ) class AppPermissionLevel(Enum): """Permission level""" CAN_MANAGE = "CAN_MANAGE" CAN_USE = "CAN_USE" @dataclass class AppPermissions: access_control_list: Optional[List[AppAccessControlResponse]] = None object_id: Optional[str] = None object_type: Optional[str] = None def as_dict(self) -> dict: """Serializes the AppPermissions into a dictionary suitable for use as a JSON request body.""" body = {} if self.access_control_list: body["access_control_list"] = [v.as_dict() for v in self.access_control_list] if self.object_id is not None: body["object_id"] = self.object_id if self.object_type is not None: body["object_type"] = self.object_type return body def as_shallow_dict(self) -> dict: """Serializes the AppPermissions into a shallow dictionary of its immediate attributes.""" body = {} if self.access_control_list: body["access_control_list"] = self.access_control_list if self.object_id is not None: body["object_id"] = self.object_id if self.object_type is not None: body["object_type"] = self.object_type return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppPermissions: """Deserializes the AppPermissions from a dictionary.""" return cls( access_control_list=_repeated_dict(d, "access_control_list", AppAccessControlResponse), object_id=d.get("object_id", None), object_type=d.get("object_type", None), ) @dataclass class AppPermissionsDescription: description: Optional[str] = None permission_level: Optional[AppPermissionLevel] = None def as_dict(self) -> dict: """Serializes the AppPermissionsDescription into a dictionary suitable for use as a JSON request body.""" body = {} if self.description is not None: body["description"] = self.description if self.permission_level is not None: body["permission_level"] = self.permission_level.value return body def as_shallow_dict(self) -> dict: """Serializes the AppPermissionsDescription into a shallow dictionary of its immediate attributes.""" body = {} if self.description is not None: body["description"] = self.description if self.permission_level is not None: body["permission_level"] = self.permission_level return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppPermissionsDescription: """Deserializes the AppPermissionsDescription from a dictionary.""" return cls( description=d.get("description", None), permission_level=_enum(d, "permission_level", AppPermissionLevel) ) @dataclass class AppResource: name: str """Name of the App Resource.""" app: Optional[AppResourceApp] = None database: Optional[AppResourceDatabase] = None description: Optional[str] = None """Description of the App Resource.""" experiment: Optional[AppResourceExperiment] = None genie_space: Optional[AppResourceGenieSpace] = None job: Optional[AppResourceJob] = None secret: Optional[AppResourceSecret] = None serving_endpoint: Optional[AppResourceServingEndpoint] = None sql_warehouse: Optional[AppResourceSqlWarehouse] = None uc_securable: Optional[AppResourceUcSecurable] = None def as_dict(self) -> dict: """Serializes the AppResource into a dictionary suitable for use as a JSON request body.""" body = {} if self.app: body["app"] = self.app.as_dict() if self.database: body["database"] = self.database.as_dict() if self.description is not None: body["description"] = self.description if self.experiment: body["experiment"] = self.experiment.as_dict() if self.genie_space: body["genie_space"] = self.genie_space.as_dict() if self.job: body["job"] = self.job.as_dict() if self.name is not None: body["name"] = self.name if self.secret: body["secret"] = self.secret.as_dict() if self.serving_endpoint: body["serving_endpoint"] = self.serving_endpoint.as_dict() if self.sql_warehouse: body["sql_warehouse"] = self.sql_warehouse.as_dict() if self.uc_securable: body["uc_securable"] = self.uc_securable.as_dict() return body def as_shallow_dict(self) -> dict: """Serializes the AppResource into a shallow dictionary of its immediate attributes.""" body = {} if self.app: body["app"] = self.app if self.database: body["database"] = self.database if self.description is not None: body["description"] = self.description if self.experiment: body["experiment"] = self.experiment if self.genie_space: body["genie_space"] = self.genie_space if self.job: body["job"] = self.job if self.name is not None: body["name"] = self.name if self.secret: body["secret"] = self.secret if self.serving_endpoint: body["serving_endpoint"] = self.serving_endpoint if self.sql_warehouse: body["sql_warehouse"] = self.sql_warehouse if self.uc_securable: body["uc_securable"] = self.uc_securable return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppResource: """Deserializes the AppResource from a dictionary.""" return cls( app=_from_dict(d, "app", AppResourceApp), database=_from_dict(d, "database", AppResourceDatabase), description=d.get("description", None), experiment=_from_dict(d, "experiment", AppResourceExperiment), genie_space=_from_dict(d, "genie_space", AppResourceGenieSpace), job=_from_dict(d, "job", AppResourceJob), name=d.get("name", None), secret=_from_dict(d, "secret", AppResourceSecret), serving_endpoint=_from_dict(d, "serving_endpoint", AppResourceServingEndpoint), sql_warehouse=_from_dict(d, "sql_warehouse", AppResourceSqlWarehouse), uc_securable=_from_dict(d, "uc_securable", AppResourceUcSecurable), ) @dataclass class AppResourceApp: def as_dict(self) -> dict: """Serializes the AppResourceApp into a dictionary suitable for use as a JSON request body.""" body = {} return body def as_shallow_dict(self) -> dict: """Serializes the AppResourceApp into a shallow dictionary of its immediate attributes.""" body = {} return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppResourceApp: """Deserializes the AppResourceApp from a dictionary.""" return cls() @dataclass class AppResourceDatabase: instance_name: str database_name: str permission: AppResourceDatabaseDatabasePermission def as_dict(self) -> dict: """Serializes the AppResourceDatabase into a dictionary suitable for use as a JSON request body.""" body = {} if self.database_name is not None: body["database_name"] = self.database_name if self.instance_name is not None: body["instance_name"] = self.instance_name if self.permission is not None: body["permission"] = self.permission.value return body def as_shallow_dict(self) -> dict: """Serializes the AppResourceDatabase into a shallow dictionary of its immediate attributes.""" body = {} if self.database_name is not None: body["database_name"] = self.database_name if self.instance_name is not None: body["instance_name"] = self.instance_name if self.permission is not None: body["permission"] = self.permission return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppResourceDatabase: """Deserializes the AppResourceDatabase from a dictionary.""" return cls( database_name=d.get("database_name", None), instance_name=d.get("instance_name", None), permission=_enum(d, "permission", AppResourceDatabaseDatabasePermission), ) class AppResourceDatabaseDatabasePermission(Enum): CAN_CONNECT_AND_CREATE = "CAN_CONNECT_AND_CREATE" @dataclass class AppResourceExperiment: experiment_id: str permission: AppResourceExperimentExperimentPermission def as_dict(self) -> dict: """Serializes the AppResourceExperiment into a dictionary suitable for use as a JSON request body.""" body = {} if self.experiment_id is not None: body["experiment_id"] = self.experiment_id if self.permission is not None: body["permission"] = self.permission.value return body def as_shallow_dict(self) -> dict: """Serializes the AppResourceExperiment into a shallow dictionary of its immediate attributes.""" body = {} if self.experiment_id is not None: body["experiment_id"] = self.experiment_id if self.permission is not None: body["permission"] = self.permission return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppResourceExperiment: """Deserializes the AppResourceExperiment from a dictionary.""" return cls( experiment_id=d.get("experiment_id", None), permission=_enum(d, "permission", AppResourceExperimentExperimentPermission), ) class AppResourceExperimentExperimentPermission(Enum): CAN_EDIT = "CAN_EDIT" CAN_MANAGE = "CAN_MANAGE" CAN_READ = "CAN_READ" @dataclass class AppResourceGenieSpace: name: str space_id: str permission: AppResourceGenieSpaceGenieSpacePermission def as_dict(self) -> dict: """Serializes the AppResourceGenieSpace into a dictionary suitable for use as a JSON request body.""" body = {} if self.name is not None: body["name"] = self.name if self.permission is not None: body["permission"] = self.permission.value if self.space_id is not None: body["space_id"] = self.space_id return body def as_shallow_dict(self) -> dict: """Serializes the AppResourceGenieSpace into a shallow dictionary of its immediate attributes.""" body = {} if self.name is not None: body["name"] = self.name if self.permission is not None: body["permission"] = self.permission if self.space_id is not None: body["space_id"] = self.space_id return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppResourceGenieSpace: """Deserializes the AppResourceGenieSpace from a dictionary.""" return cls( name=d.get("name", None), permission=_enum(d, "permission", AppResourceGenieSpaceGenieSpacePermission), space_id=d.get("space_id", None), ) class AppResourceGenieSpaceGenieSpacePermission(Enum): CAN_EDIT = "CAN_EDIT" CAN_MANAGE = "CAN_MANAGE" CAN_RUN = "CAN_RUN" CAN_VIEW = "CAN_VIEW" @dataclass class AppResourceJob: id: str """Id of the job to grant permission on.""" permission: AppResourceJobJobPermission """Permissions to grant on the Job. Supported permissions are: "CAN_MANAGE", "IS_OWNER", "CAN_MANAGE_RUN", "CAN_VIEW".""" def as_dict(self) -> dict: """Serializes the AppResourceJob into a dictionary suitable for use as a JSON request body.""" body = {} if self.id is not None: body["id"] = self.id if self.permission is not None: body["permission"] = self.permission.value return body def as_shallow_dict(self) -> dict: """Serializes the AppResourceJob into a shallow dictionary of its immediate attributes.""" body = {} if self.id is not None: body["id"] = self.id if self.permission is not None: body["permission"] = self.permission return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppResourceJob: """Deserializes the AppResourceJob from a dictionary.""" return cls(id=d.get("id", None), permission=_enum(d, "permission", AppResourceJobJobPermission)) class AppResourceJobJobPermission(Enum): CAN_MANAGE = "CAN_MANAGE" CAN_MANAGE_RUN = "CAN_MANAGE_RUN" CAN_VIEW = "CAN_VIEW" IS_OWNER = "IS_OWNER" @dataclass class AppResourceSecret: scope: str """Scope of the secret to grant permission on.""" key: str """Key of the secret to grant permission on.""" permission: AppResourceSecretSecretPermission """Permission to grant on the secret scope. For secrets, only one permission is allowed. Permission must be one of: "READ", "WRITE", "MANAGE".""" def as_dict(self) -> dict: """Serializes the AppResourceSecret into a dictionary suitable for use as a JSON request body.""" body = {} if self.key is not None: body["key"] = self.key if self.permission is not None: body["permission"] = self.permission.value if self.scope is not None: body["scope"] = self.scope return body def as_shallow_dict(self) -> dict: """Serializes the AppResourceSecret into a shallow dictionary of its immediate attributes.""" body = {} if self.key is not None: body["key"] = self.key if self.permission is not None: body["permission"] = self.permission if self.scope is not None: body["scope"] = self.scope return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppResourceSecret: """Deserializes the AppResourceSecret from a dictionary.""" return cls( key=d.get("key", None), permission=_enum(d, "permission", AppResourceSecretSecretPermission), scope=d.get("scope", None), ) class AppResourceSecretSecretPermission(Enum): """Permission to grant on the secret scope. Supported permissions are: "READ", "WRITE", "MANAGE".""" MANAGE = "MANAGE" READ = "READ" WRITE = "WRITE" @dataclass class AppResourceServingEndpoint: name: str """Name of the serving endpoint to grant permission on.""" permission: AppResourceServingEndpointServingEndpointPermission """Permission to grant on the serving endpoint. Supported permissions are: "CAN_MANAGE", "CAN_QUERY", "CAN_VIEW".""" def as_dict(self) -> dict: """Serializes the AppResourceServingEndpoint into a dictionary suitable for use as a JSON request body.""" body = {} if self.name is not None: body["name"] = self.name if self.permission is not None: body["permission"] = self.permission.value return body def as_shallow_dict(self) -> dict: """Serializes the AppResourceServingEndpoint into a shallow dictionary of its immediate attributes.""" body = {} if self.name is not None: body["name"] = self.name if self.permission is not None: body["permission"] = self.permission return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppResourceServingEndpoint: """Deserializes the AppResourceServingEndpoint from a dictionary.""" return cls( name=d.get("name", None), permission=_enum(d, "permission", AppResourceServingEndpointServingEndpointPermission), ) class AppResourceServingEndpointServingEndpointPermission(Enum): CAN_MANAGE = "CAN_MANAGE" CAN_QUERY = "CAN_QUERY" CAN_VIEW = "CAN_VIEW" @dataclass class AppResourceSqlWarehouse: id: str """Id of the SQL warehouse to grant permission on.""" permission: AppResourceSqlWarehouseSqlWarehousePermission """Permission to grant on the SQL warehouse. Supported permissions are: "CAN_MANAGE", "CAN_USE", "IS_OWNER".""" def as_dict(self) -> dict: """Serializes the AppResourceSqlWarehouse into a dictionary suitable for use as a JSON request body.""" body = {} if self.id is not None: body["id"] = self.id if self.permission is not None: body["permission"] = self.permission.value return body def as_shallow_dict(self) -> dict: """Serializes the AppResourceSqlWarehouse into a shallow dictionary of its immediate attributes.""" body = {} if self.id is not None: body["id"] = self.id if self.permission is not None: body["permission"] = self.permission return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppResourceSqlWarehouse: """Deserializes the AppResourceSqlWarehouse from a dictionary.""" return cls( id=d.get("id", None), permission=_enum(d, "permission", AppResourceSqlWarehouseSqlWarehousePermission) ) class AppResourceSqlWarehouseSqlWarehousePermission(Enum): CAN_MANAGE = "CAN_MANAGE" CAN_USE = "CAN_USE" IS_OWNER = "IS_OWNER" @dataclass class AppResourceUcSecurable: securable_full_name: str securable_type: AppResourceUcSecurableUcSecurableType permission: AppResourceUcSecurableUcSecurablePermission securable_kind: Optional[str] = None """The securable kind from Unity Catalog. See https://docs.databricks.com/api/workspace/tables/get#securable_kind_manifest-securable_kind.""" def as_dict(self) -> dict: """Serializes the AppResourceUcSecurable into a dictionary suitable for use as a JSON request body.""" body = {} if self.permission is not None: body["permission"] = self.permission.value if self.securable_full_name is not None: body["securable_full_name"] = self.securable_full_name if self.securable_kind is not None: body["securable_kind"] = self.securable_kind if self.securable_type is not None: body["securable_type"] = self.securable_type.value return body def as_shallow_dict(self) -> dict: """Serializes the AppResourceUcSecurable into a shallow dictionary of its immediate attributes.""" body = {} if self.permission is not None: body["permission"] = self.permission if self.securable_full_name is not None: body["securable_full_name"] = self.securable_full_name if self.securable_kind is not None: body["securable_kind"] = self.securable_kind if self.securable_type is not None: body["securable_type"] = self.securable_type return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppResourceUcSecurable: """Deserializes the AppResourceUcSecurable from a dictionary.""" return cls( permission=_enum(d, "permission", AppResourceUcSecurableUcSecurablePermission), securable_full_name=d.get("securable_full_name", None), securable_kind=d.get("securable_kind", None), securable_type=_enum(d, "securable_type", AppResourceUcSecurableUcSecurableType), ) class AppResourceUcSecurableUcSecurablePermission(Enum): EXECUTE = "EXECUTE" MODIFY = "MODIFY" READ_VOLUME = "READ_VOLUME" SELECT = "SELECT" USE_CONNECTION = "USE_CONNECTION" WRITE_VOLUME = "WRITE_VOLUME" class AppResourceUcSecurableUcSecurableType(Enum): CONNECTION = "CONNECTION" FUNCTION = "FUNCTION" TABLE = "TABLE" VOLUME = "VOLUME" @dataclass class AppUpdate: budget_policy_id: Optional[str] = None compute_size: Optional[ComputeSize] = None description: Optional[str] = None git_repository: Optional[GitRepository] = None resources: Optional[List[AppResource]] = None status: Optional[AppUpdateUpdateStatus] = None usage_policy_id: Optional[str] = None user_api_scopes: Optional[List[str]] = None def as_dict(self) -> dict: """Serializes the AppUpdate into a dictionary suitable for use as a JSON request body.""" body = {} if self.budget_policy_id is not None: body["budget_policy_id"] = self.budget_policy_id if self.compute_size is not None: body["compute_size"] = self.compute_size.value if self.description is not None: body["description"] = self.description if self.git_repository: body["git_repository"] = self.git_repository.as_dict() if self.resources: body["resources"] = [v.as_dict() for v in self.resources] if self.status: body["status"] = self.status.as_dict() if self.usage_policy_id is not None: body["usage_policy_id"] = self.usage_policy_id if self.user_api_scopes: body["user_api_scopes"] = [v for v in self.user_api_scopes] return body def as_shallow_dict(self) -> dict: """Serializes the AppUpdate into a shallow dictionary of its immediate attributes.""" body = {} if self.budget_policy_id is not None: body["budget_policy_id"] = self.budget_policy_id if self.compute_size is not None: body["compute_size"] = self.compute_size if self.description is not None: body["description"] = self.description if self.git_repository: body["git_repository"] = self.git_repository if self.resources: body["resources"] = self.resources if self.status: body["status"] = self.status if self.usage_policy_id is not None: body["usage_policy_id"] = self.usage_policy_id if self.user_api_scopes: body["user_api_scopes"] = self.user_api_scopes return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppUpdate: """Deserializes the AppUpdate from a dictionary.""" return cls( budget_policy_id=d.get("budget_policy_id", None), compute_size=_enum(d, "compute_size", ComputeSize), description=d.get("description", None), git_repository=_from_dict(d, "git_repository", GitRepository), resources=_repeated_dict(d, "resources", AppResource), status=_from_dict(d, "status", AppUpdateUpdateStatus), usage_policy_id=d.get("usage_policy_id", None), user_api_scopes=d.get("user_api_scopes", None), ) @dataclass class AppUpdateUpdateStatus: message: Optional[str] = None state: Optional[AppUpdateUpdateStatusUpdateState] = None def as_dict(self) -> dict: """Serializes the AppUpdateUpdateStatus into a dictionary suitable for use as a JSON request body.""" body = {} if self.message is not None: body["message"] = self.message if self.state is not None: body["state"] = self.state.value return body def as_shallow_dict(self) -> dict: """Serializes the AppUpdateUpdateStatus into a shallow dictionary of its immediate attributes.""" body = {} if self.message is not None: body["message"] = self.message if self.state is not None: body["state"] = self.state return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> AppUpdateUpdateStatus: """Deserializes the AppUpdateUpdateStatus from a dictionary.""" return cls(message=d.get("message", None), state=_enum(d, "state", AppUpdateUpdateStatusUpdateState)) class AppUpdateUpdateStatusUpdateState(Enum): FAILED = "FAILED" IN_PROGRESS = "IN_PROGRESS" NOT_UPDATED = "NOT_UPDATED" SUCCEEDED = "SUCCEEDED" class ApplicationState(Enum): CRASHED = "CRASHED" DEPLOYING = "DEPLOYING" RUNNING = "RUNNING" UNAVAILABLE = "UNAVAILABLE" @dataclass class ApplicationStatus: message: Optional[str] = None """Application status message""" state: Optional[ApplicationState] = None """State of the application.""" def as_dict(self) -> dict: """Serializes the ApplicationStatus into a dictionary suitable for use as a JSON request body.""" body = {} if self.message is not None: body["message"] = self.message if self.state is not None: body["state"] = self.state.value return body def as_shallow_dict(self) -> dict: """Serializes the ApplicationStatus into a shallow dictionary of its immediate attributes.""" body = {} if self.message is not None: body["message"] = self.message if self.state is not None: body["state"] = self.state return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> ApplicationStatus: """Deserializes the ApplicationStatus from a dictionary.""" return cls(message=d.get("message", None), state=_enum(d, "state", ApplicationState)) class ComputeSize(Enum): LARGE = "LARGE" MEDIUM = "MEDIUM" class ComputeState(Enum): ACTIVE = "ACTIVE" DELETING = "DELETING" ERROR = "ERROR" STARTING = "STARTING" STOPPED = "STOPPED" STOPPING = "STOPPING" UPDATING = "UPDATING" @dataclass class ComputeStatus: active_instances: Optional[int] = None """The number of compute instances currently serving requests for this application. An instance is considered active if it is reachable and ready to handle requests.""" message: Optional[str] = None """Compute status message""" state: Optional[ComputeState] = None """State of the app compute.""" def as_dict(self) -> dict: """Serializes the ComputeStatus into a dictionary suitable for use as a JSON request body.""" body = {} if self.active_instances is not None: body["active_instances"] = self.active_instances if self.message is not None: body["message"] = self.message if self.state is not None: body["state"] = self.state.value return body def as_shallow_dict(self) -> dict: """Serializes the ComputeStatus into a shallow dictionary of its immediate attributes.""" body = {} if self.active_instances is not None: body["active_instances"] = self.active_instances if self.message is not None: body["message"] = self.message if self.state is not None: body["state"] = self.state return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> ComputeStatus: """Deserializes the ComputeStatus from a dictionary.""" return cls( active_instances=d.get("active_instances", None), message=d.get("message", None), state=_enum(d, "state", ComputeState), ) @dataclass class CustomTemplate: name: str """The name of the template. It must contain only alphanumeric characters, hyphens, underscores, and whitespaces. It must be unique within the workspace.""" git_repo: str """The Git repository URL that the template resides in.""" path: str """The path to the template within the Git repository.""" manifest: AppManifest """The manifest of the template. It defines fields and default values when installing the template.""" git_provider: str """The Git provider of the template.""" creator: Optional[str] = None description: Optional[str] = None """The description of the template.""" def as_dict(self) -> dict: """Serializes the CustomTemplate into a dictionary suitable for use as a JSON request body.""" body = {} if self.creator is not None: body["creator"] = self.creator if self.description is not None: body["description"] = self.description if self.git_provider is not None: body["git_provider"] = self.git_provider if self.git_repo is not None: body["git_repo"] = self.git_repo if self.manifest: body["manifest"] = self.manifest.as_dict() if self.name is not None: body["name"] = self.name if self.path is not None: body["path"] = self.path return body def as_shallow_dict(self) -> dict: """Serializes the CustomTemplate into a shallow dictionary of its immediate attributes.""" body = {} if self.creator is not None: body["creator"] = self.creator if self.description is not None: body["description"] = self.description if self.git_provider is not None: body["git_provider"] = self.git_provider if self.git_repo is not None: body["git_repo"] = self.git_repo if self.manifest: body["manifest"] = self.manifest if self.name is not None: body["name"] = self.name if self.path is not None: body["path"] = self.path return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> CustomTemplate: """Deserializes the CustomTemplate from a dictionary.""" return cls( creator=d.get("creator", None), description=d.get("description", None), git_provider=d.get("git_provider", None), git_repo=d.get("git_repo", None), manifest=_from_dict(d, "manifest", AppManifest), name=d.get("name", None), path=d.get("path", None), ) @dataclass class DatabricksServiceExceptionWithDetailsProto: """Databricks Error that is returned by all Databricks APIs.""" details: Optional[List[dict]] = None error_code: Optional[ErrorCode] = None message: Optional[str] = None stack_trace: Optional[str] = None def as_dict(self) -> dict: """Serializes the DatabricksServiceExceptionWithDetailsProto into a dictionary suitable for use as a JSON request body.""" body = {} if self.details: body["details"] = [v for v in self.details] if self.error_code is not None: body["error_code"] = self.error_code.value if self.message is not None: body["message"] = self.message if self.stack_trace is not None: body["stack_trace"] = self.stack_trace return body def as_shallow_dict(self) -> dict: """Serializes the DatabricksServiceExceptionWithDetailsProto into a shallow dictionary of its immediate attributes.""" body = {} if self.details: body["details"] = self.details if self.error_code is not None: body["error_code"] = self.error_code if self.message is not None: body["message"] = self.message if self.stack_trace is not None: body["stack_trace"] = self.stack_trace return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> DatabricksServiceExceptionWithDetailsProto: """Deserializes the DatabricksServiceExceptionWithDetailsProto from a dictionary.""" return cls( details=d.get("details", None), error_code=_enum(d, "error_code", ErrorCode), message=d.get("message", None), stack_trace=d.get("stack_trace", None), ) @dataclass class EnvVar: name: Optional[str] = None """The name of the environment variable.""" value: Optional[str] = None """The value for the environment variable.""" value_from: Optional[str] = None """The name of an external Databricks resource that contains the value, such as a secret or a database table.""" def as_dict(self) -> dict: """Serializes the EnvVar into a dictionary suitable for use as a JSON request body.""" body = {} if self.name is not None: body["name"] = self.name if self.value is not None: body["value"] = self.value if self.value_from is not None: body["value_from"] = self.value_from return body def as_shallow_dict(self) -> dict: """Serializes the EnvVar into a shallow dictionary of its immediate attributes.""" body = {} if self.name is not None: body["name"] = self.name if self.value is not None: body["value"] = self.value if self.value_from is not None: body["value_from"] = self.value_from return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> EnvVar: """Deserializes the EnvVar from a dictionary.""" return cls(name=d.get("name", None), value=d.get("value", None), value_from=d.get("value_from", None)) class ErrorCode(Enum): """Error codes returned by Databricks APIs to indicate specific failure conditions.""" ABORTED = "ABORTED" ALREADY_EXISTS = "ALREADY_EXISTS" BAD_REQUEST = "BAD_REQUEST" CANCELLED = "CANCELLED" CATALOG_ALREADY_EXISTS = "CATALOG_ALREADY_EXISTS" CATALOG_DOES_NOT_EXIST = "CATALOG_DOES_NOT_EXIST" CATALOG_NOT_EMPTY = "CATALOG_NOT_EMPTY" COULD_NOT_ACQUIRE_LOCK = "COULD_NOT_ACQUIRE_LOCK" CUSTOMER_UNAUTHORIZED = "CUSTOMER_UNAUTHORIZED" DAC_ALREADY_EXISTS = "DAC_ALREADY_EXISTS" DAC_DOES_NOT_EXIST = "DAC_DOES_NOT_EXIST" DATA_LOSS = "DATA_LOSS" DEADLINE_EXCEEDED = "DEADLINE_EXCEEDED" DEPLOYMENT_TIMEOUT = "DEPLOYMENT_TIMEOUT" DIRECTORY_NOT_EMPTY = "DIRECTORY_NOT_EMPTY" DIRECTORY_PROTECTED = "DIRECTORY_PROTECTED" DRY_RUN_FAILED = "DRY_RUN_FAILED" ENDPOINT_NOT_FOUND = "ENDPOINT_NOT_FOUND" EXTERNAL_LOCATION_ALREADY_EXISTS = "EXTERNAL_LOCATION_ALREADY_EXISTS" EXTERNAL_LOCATION_DOES_NOT_EXIST = "EXTERNAL_LOCATION_DOES_NOT_EXIST" FEATURE_DISABLED = "FEATURE_DISABLED" GIT_CONFLICT = "GIT_CONFLICT" GIT_REMOTE_ERROR = "GIT_REMOTE_ERROR" GIT_SENSITIVE_TOKEN_DETECTED = "GIT_SENSITIVE_TOKEN_DETECTED" GIT_UNKNOWN_REF = "GIT_UNKNOWN_REF" GIT_URL_NOT_ON_ALLOW_LIST = "GIT_URL_NOT_ON_ALLOW_LIST" INSECURE_PARTNER_RESPONSE = "INSECURE_PARTNER_RESPONSE" INTERNAL_ERROR = "INTERNAL_ERROR" INVALID_PARAMETER_VALUE = "INVALID_PARAMETER_VALUE" INVALID_STATE = "INVALID_STATE" INVALID_STATE_TRANSITION = "INVALID_STATE_TRANSITION" IO_ERROR = "IO_ERROR" IPYNB_FILE_IN_REPO = "IPYNB_FILE_IN_REPO" MALFORMED_PARTNER_RESPONSE = "MALFORMED_PARTNER_RESPONSE" MALFORMED_REQUEST = "MALFORMED_REQUEST" MANAGED_RESOURCE_GROUP_DOES_NOT_EXIST = "MANAGED_RESOURCE_GROUP_DOES_NOT_EXIST" MAX_BLOCK_SIZE_EXCEEDED = "MAX_BLOCK_SIZE_EXCEEDED" MAX_CHILD_NODE_SIZE_EXCEEDED = "MAX_CHILD_NODE_SIZE_EXCEEDED" MAX_LIST_SIZE_EXCEEDED = "MAX_LIST_SIZE_EXCEEDED" MAX_NOTEBOOK_SIZE_EXCEEDED = "MAX_NOTEBOOK_SIZE_EXCEEDED" MAX_READ_SIZE_EXCEEDED = "MAX_READ_SIZE_EXCEEDED" METASTORE_ALREADY_EXISTS = "METASTORE_ALREADY_EXISTS" METASTORE_DOES_NOT_EXIST = "METASTORE_DOES_NOT_EXIST" METASTORE_NOT_EMPTY = "METASTORE_NOT_EMPTY" NOT_FOUND = "NOT_FOUND" NOT_IMPLEMENTED = "NOT_IMPLEMENTED" PARTIAL_DELETE = "PARTIAL_DELETE" PERMISSION_DENIED = "PERMISSION_DENIED" PERMISSION_NOT_PROPAGATED = "PERMISSION_NOT_PROPAGATED" PRINCIPAL_DOES_NOT_EXIST = "PRINCIPAL_DOES_NOT_EXIST" PROJECTS_OPERATION_TIMEOUT = "PROJECTS_OPERATION_TIMEOUT" PROVIDER_ALREADY_EXISTS = "PROVIDER_ALREADY_EXISTS" PROVIDER_DOES_NOT_EXIST = "PROVIDER_DOES_NOT_EXIST" PROVIDER_SHARE_NOT_ACCESSIBLE = "PROVIDER_SHARE_NOT_ACCESSIBLE" QUOTA_EXCEEDED = "QUOTA_EXCEEDED" RECIPIENT_ALREADY_EXISTS = "RECIPIENT_ALREADY_EXISTS" RECIPIENT_DOES_NOT_EXIST = "RECIPIENT_DOES_NOT_EXIST" REQUEST_LIMIT_EXCEEDED = "REQUEST_LIMIT_EXCEEDED" RESOURCE_ALREADY_EXISTS = "RESOURCE_ALREADY_EXISTS" RESOURCE_CONFLICT = "RESOURCE_CONFLICT" RESOURCE_DOES_NOT_EXIST = "RESOURCE_DOES_NOT_EXIST" RESOURCE_EXHAUSTED = "RESOURCE_EXHAUSTED" RESOURCE_LIMIT_EXCEEDED = "RESOURCE_LIMIT_EXCEEDED" SCHEMA_ALREADY_EXISTS = "SCHEMA_ALREADY_EXISTS" SCHEMA_DOES_NOT_EXIST = "SCHEMA_DOES_NOT_EXIST" SCHEMA_NOT_EMPTY = "SCHEMA_NOT_EMPTY" SEARCH_QUERY_TOO_LONG = "SEARCH_QUERY_TOO_LONG" SEARCH_QUERY_TOO_SHORT = "SEARCH_QUERY_TOO_SHORT" SERVICE_UNDER_MAINTENANCE = "SERVICE_UNDER_MAINTENANCE" SHARE_ALREADY_EXISTS = "SHARE_ALREADY_EXISTS" SHARE_DOES_NOT_EXIST = "SHARE_DOES_NOT_EXIST" STORAGE_CREDENTIAL_ALREADY_EXISTS = "STORAGE_CREDENTIAL_ALREADY_EXISTS" STORAGE_CREDENTIAL_DOES_NOT_EXIST = "STORAGE_CREDENTIAL_DOES_NOT_EXIST" TABLE_ALREADY_EXISTS = "TABLE_ALREADY_EXISTS" TABLE_DOES_NOT_EXIST = "TABLE_DOES_NOT_EXIST" TEMPORARILY_UNAVAILABLE = "TEMPORARILY_UNAVAILABLE" UNAUTHENTICATED = "UNAUTHENTICATED" UNAVAILABLE = "UNAVAILABLE" UNKNOWN = "UNKNOWN" UNPARSEABLE_HTTP_ERROR = "UNPARSEABLE_HTTP_ERROR" WORKSPACE_TEMPORARILY_UNAVAILABLE = "WORKSPACE_TEMPORARILY_UNAVAILABLE" @dataclass class GetAppPermissionLevelsResponse: permission_levels: Optional[List[AppPermissionsDescription]] = None """Specific permission levels""" def as_dict(self) -> dict: """Serializes the GetAppPermissionLevelsResponse into a dictionary suitable for use as a JSON request body.""" body = {} if self.permission_levels: body["permission_levels"] = [v.as_dict() for v in self.permission_levels] return body def as_shallow_dict(self) -> dict: """Serializes the GetAppPermissionLevelsResponse into a shallow dictionary of its immediate attributes.""" body = {} if self.permission_levels: body["permission_levels"] = self.permission_levels return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GetAppPermissionLevelsResponse: """Deserializes the GetAppPermissionLevelsResponse from a dictionary.""" return cls(permission_levels=_repeated_dict(d, "permission_levels", AppPermissionsDescription)) @dataclass class GitRepository: """Git repository configuration specifying the location of the repository.""" url: str """URL of the Git repository.""" provider: str """Git provider. Case insensitive. Supported values: gitHub, gitHubEnterprise, bitbucketCloud, bitbucketServer, azureDevOpsServices, gitLab, gitLabEnterpriseEdition, awsCodeCommit.""" def as_dict(self) -> dict: """Serializes the GitRepository into a dictionary suitable for use as a JSON request body.""" body = {} if self.provider is not None: body["provider"] = self.provider if self.url is not None: body["url"] = self.url return body def as_shallow_dict(self) -> dict: """Serializes the GitRepository into a shallow dictionary of its immediate attributes.""" body = {} if self.provider is not None: body["provider"] = self.provider if self.url is not None: body["url"] = self.url return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GitRepository: """Deserializes the GitRepository from a dictionary.""" return cls(provider=d.get("provider", None), url=d.get("url", None)) @dataclass class GitSource: """Complete git source specification including repository location and reference.""" branch: Optional[str] = None """Git branch to checkout.""" commit: Optional[str] = None """Git commit SHA to checkout.""" git_repository: Optional[GitRepository] = None """Git repository configuration. Populated from the app's git_repository configuration.""" resolved_commit: Optional[str] = None """The resolved commit SHA that was actually used for the deployment. This is populated by the system after resolving the reference (branch, tag, or commit). If commit is specified directly, this will match commit. If a branch or tag is specified, this contains the commit SHA that the branch or tag pointed to at deployment time.""" source_code_path: Optional[str] = None """Relative path to the app source code within the Git repository. If not specified, the root of the repository is used.""" tag: Optional[str] = None """Git tag to checkout.""" def as_dict(self) -> dict: """Serializes the GitSource into a dictionary suitable for use as a JSON request body.""" body = {} if self.branch is not None: body["branch"] = self.branch if self.commit is not None: body["commit"] = self.commit if self.git_repository: body["git_repository"] = self.git_repository.as_dict() if self.resolved_commit is not None: body["resolved_commit"] = self.resolved_commit if self.source_code_path is not None: body["source_code_path"] = self.source_code_path if self.tag is not None: body["tag"] = self.tag return body def as_shallow_dict(self) -> dict: """Serializes the GitSource into a shallow dictionary of its immediate attributes.""" body = {} if self.branch is not None: body["branch"] = self.branch if self.commit is not None: body["commit"] = self.commit if self.git_repository: body["git_repository"] = self.git_repository if self.resolved_commit is not None: body["resolved_commit"] = self.resolved_commit if self.source_code_path is not None: body["source_code_path"] = self.source_code_path if self.tag is not None: body["tag"] = self.tag return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> GitSource: """Deserializes the GitSource from a dictionary.""" return cls( branch=d.get("branch", None), commit=d.get("commit", None), git_repository=_from_dict(d, "git_repository", GitRepository), resolved_commit=d.get("resolved_commit", None), source_code_path=d.get("source_code_path", None), tag=d.get("tag", None), ) @dataclass class ListAppDeploymentsResponse: app_deployments: Optional[List[AppDeployment]] = None """Deployment history of the app.""" next_page_token: Optional[str] = None """Pagination token to request the next page of apps.""" def as_dict(self) -> dict: """Serializes the ListAppDeploymentsResponse into a dictionary suitable for use as a JSON request body.""" body = {} if self.app_deployments: body["app_deployments"] = [v.as_dict() for v in self.app_deployments] if self.next_page_token is not None: body["next_page_token"] = self.next_page_token return body def as_shallow_dict(self) -> dict: """Serializes the ListAppDeploymentsResponse into a shallow dictionary of its immediate attributes.""" body = {} if self.app_deployments: body["app_deployments"] = self.app_deployments if self.next_page_token is not None: body["next_page_token"] = self.next_page_token return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> ListAppDeploymentsResponse: """Deserializes the ListAppDeploymentsResponse from a dictionary.""" return cls( app_deployments=_repeated_dict(d, "app_deployments", AppDeployment), next_page_token=d.get("next_page_token", None), ) @dataclass class ListAppsResponse: apps: Optional[List[App]] = None next_page_token: Optional[str] = None """Pagination token to request the next page of apps.""" def as_dict(self) -> dict: """Serializes the ListAppsResponse into a dictionary suitable for use as a JSON request body.""" body = {} if self.apps: body["apps"] = [v.as_dict() for v in self.apps] if self.next_page_token is not None: body["next_page_token"] = self.next_page_token return body def as_shallow_dict(self) -> dict: """Serializes the ListAppsResponse into a shallow dictionary of its immediate attributes.""" body = {} if self.apps: body["apps"] = self.apps if self.next_page_token is not None: body["next_page_token"] = self.next_page_token return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> ListAppsResponse: """Deserializes the ListAppsResponse from a dictionary.""" return cls(apps=_repeated_dict(d, "apps", App), next_page_token=d.get("next_page_token", None)) @dataclass class ListCustomTemplatesResponse: next_page_token: Optional[str] = None """Pagination token to request the next page of custom templates.""" templates: Optional[List[CustomTemplate]] = None def as_dict(self) -> dict: """Serializes the ListCustomTemplatesResponse 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.templates: body["templates"] = [v.as_dict() for v in self.templates] return body def as_shallow_dict(self) -> dict: """Serializes the ListCustomTemplatesResponse 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.templates: body["templates"] = self.templates return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> ListCustomTemplatesResponse: """Deserializes the ListCustomTemplatesResponse from a dictionary.""" return cls( next_page_token=d.get("next_page_token", None), templates=_repeated_dict(d, "templates", CustomTemplate) ) @dataclass class ListSpacesResponse: next_page_token: Optional[str] = None """Pagination token to request the next page of app spaces.""" spaces: Optional[List[Space]] = None def as_dict(self) -> dict: """Serializes the ListSpacesResponse 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.spaces: body["spaces"] = [v.as_dict() for v in self.spaces] return body def as_shallow_dict(self) -> dict: """Serializes the ListSpacesResponse 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.spaces: body["spaces"] = self.spaces return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> ListSpacesResponse: """Deserializes the ListSpacesResponse from a dictionary.""" return cls(next_page_token=d.get("next_page_token", None), spaces=_repeated_dict(d, "spaces", Space)) @dataclass class Operation: """This resource represents a long-running operation that is the result of a network API call.""" done: Optional[bool] = None """If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available.""" error: Optional[DatabricksServiceExceptionWithDetailsProto] = None """The error result of the operation in case of failure or cancellation.""" metadata: Optional[dict] = None """Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata.""" name: Optional[str] = None """The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`.""" response: Optional[dict] = None """The normal, successful response of the operation.""" def as_dict(self) -> dict: """Serializes the Operation into a dictionary suitable for use as a JSON request body.""" body = {} if self.done is not None: body["done"] = self.done if self.error: body["error"] = self.error.as_dict() if self.metadata: body["metadata"] = self.metadata if self.name is not None: body["name"] = self.name if self.response: body["response"] = self.response return body def as_shallow_dict(self) -> dict: """Serializes the Operation into a shallow dictionary of its immediate attributes.""" body = {} if self.done is not None: body["done"] = self.done if self.error: body["error"] = self.error if self.metadata: body["metadata"] = self.metadata if self.name is not None: body["name"] = self.name if self.response: body["response"] = self.response return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> Operation: """Deserializes the Operation from a dictionary.""" return cls( done=d.get("done", None), error=_from_dict(d, "error", DatabricksServiceExceptionWithDetailsProto), metadata=d.get("metadata", None), name=d.get("name", None), response=d.get("response", None), ) @dataclass class Space: name: str """The name of the app space. The name must contain only lowercase alphanumeric characters and hyphens. It must be unique within the workspace.""" create_time: Optional[Timestamp] = None """The creation time of the app space. Formatted timestamp in ISO 6801.""" creator: Optional[str] = None """The email of the user that created the app space.""" description: Optional[str] = None """The description of the app space.""" effective_usage_policy_id: Optional[str] = None """The effective usage policy ID used by apps in the space.""" effective_user_api_scopes: Optional[List[str]] = None """The effective api scopes granted to the user access token.""" id: Optional[str] = None """The unique identifier of the app space.""" oauth2_app_client_id: Optional[str] = None """The OAuth2 app client ID for the app space.""" oauth2_app_integration_id: Optional[str] = None """The OAuth2 app integration ID for the app space.""" resources: Optional[List[AppResource]] = None """Resources for the app space. Resources configured at the space level are available to all apps in the space.""" service_principal_client_id: Optional[str] = None """The service principal client ID for the app space.""" service_principal_id: Optional[int] = None """The service principal ID for the app space.""" service_principal_name: Optional[str] = None """The service principal name for the app space.""" status: Optional[SpaceStatus] = None """The status of the app space.""" update_time: Optional[Timestamp] = None """The update time of the app space. Formatted timestamp in ISO 6801.""" updater: Optional[str] = None """The email of the user that last updated the app space.""" usage_policy_id: Optional[str] = None """The usage policy ID for managing cost at the space level.""" user_api_scopes: Optional[List[str]] = None """OAuth scopes for apps in the space.""" def as_dict(self) -> dict: """Serializes the Space into a dictionary suitable for use as a JSON request body.""" body = {} if self.create_time is not None: body["create_time"] = self.create_time.ToJsonString() if self.creator is not None: body["creator"] = self.creator if self.description is not None: body["description"] = self.description if self.effective_usage_policy_id is not None: body["effective_usage_policy_id"] = self.effective_usage_policy_id if self.effective_user_api_scopes: body["effective_user_api_scopes"] = [v for v in self.effective_user_api_scopes] if self.id is not None: body["id"] = self.id if self.name is not None: body["name"] = self.name if self.oauth2_app_client_id is not None: body["oauth2_app_client_id"] = self.oauth2_app_client_id if self.oauth2_app_integration_id is not None: body["oauth2_app_integration_id"] = self.oauth2_app_integration_id if self.resources: body["resources"] = [v.as_dict() for v in self.resources] if self.service_principal_client_id is not None: body["service_principal_client_id"] = self.service_principal_client_id if self.service_principal_id is not None: body["service_principal_id"] = self.service_principal_id if self.service_principal_name is not None: body["service_principal_name"] = self.service_principal_name if self.status: body["status"] = self.status.as_dict() if self.update_time is not None: body["update_time"] = self.update_time.ToJsonString() if self.updater is not None: body["updater"] = self.updater if self.usage_policy_id is not None: body["usage_policy_id"] = self.usage_policy_id if self.user_api_scopes: body["user_api_scopes"] = [v for v in self.user_api_scopes] return body def as_shallow_dict(self) -> dict: """Serializes the Space into a shallow dictionary of its immediate attributes.""" body = {} if self.create_time is not None: body["create_time"] = self.create_time if self.creator is not None: body["creator"] = self.creator if self.description is not None: body["description"] = self.description if self.effective_usage_policy_id is not None: body["effective_usage_policy_id"] = self.effective_usage_policy_id if self.effective_user_api_scopes: body["effective_user_api_scopes"] = self.effective_user_api_scopes if self.id is not None: body["id"] = self.id if self.name is not None: body["name"] = self.name if self.oauth2_app_client_id is not None: body["oauth2_app_client_id"] = self.oauth2_app_client_id if self.oauth2_app_integration_id is not None: body["oauth2_app_integration_id"] = self.oauth2_app_integration_id if self.resources: body["resources"] = self.resources if self.service_principal_client_id is not None: body["service_principal_client_id"] = self.service_principal_client_id if self.service_principal_id is not None: body["service_principal_id"] = self.service_principal_id if self.service_principal_name is not None: body["service_principal_name"] = self.service_principal_name if self.status: body["status"] = self.status if self.update_time is not None: body["update_time"] = self.update_time if self.updater is not None: body["updater"] = self.updater if self.usage_policy_id is not None: body["usage_policy_id"] = self.usage_policy_id if self.user_api_scopes: body["user_api_scopes"] = self.user_api_scopes return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> Space: """Deserializes the Space from a dictionary.""" return cls( create_time=_timestamp(d, "create_time"), creator=d.get("creator", None), description=d.get("description", None), effective_usage_policy_id=d.get("effective_usage_policy_id", None), effective_user_api_scopes=d.get("effective_user_api_scopes", None), id=d.get("id", None), name=d.get("name", None), oauth2_app_client_id=d.get("oauth2_app_client_id", None), oauth2_app_integration_id=d.get("oauth2_app_integration_id", None), resources=_repeated_dict(d, "resources", AppResource), service_principal_client_id=d.get("service_principal_client_id", None), service_principal_id=d.get("service_principal_id", None), service_principal_name=d.get("service_principal_name", None), status=_from_dict(d, "status", SpaceStatus), update_time=_timestamp(d, "update_time"), updater=d.get("updater", None), usage_policy_id=d.get("usage_policy_id", None), user_api_scopes=d.get("user_api_scopes", None), ) @dataclass class SpaceStatus: message: Optional[str] = None """Message providing context about the current state.""" state: Optional[SpaceStatusSpaceState] = None """The state of the app space.""" def as_dict(self) -> dict: """Serializes the SpaceStatus into a dictionary suitable for use as a JSON request body.""" body = {} if self.message is not None: body["message"] = self.message if self.state is not None: body["state"] = self.state.value return body def as_shallow_dict(self) -> dict: """Serializes the SpaceStatus into a shallow dictionary of its immediate attributes.""" body = {} if self.message is not None: body["message"] = self.message if self.state is not None: body["state"] = self.state return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> SpaceStatus: """Deserializes the SpaceStatus from a dictionary.""" return cls(message=d.get("message", None), state=_enum(d, "state", SpaceStatusSpaceState)) class SpaceStatusSpaceState(Enum): SPACE_ACTIVE = "SPACE_ACTIVE" SPACE_CREATING = "SPACE_CREATING" SPACE_DELETED = "SPACE_DELETED" SPACE_DELETING = "SPACE_DELETING" SPACE_ERROR = "SPACE_ERROR" SPACE_UPDATING = "SPACE_UPDATING" @dataclass class SpaceUpdate: """Tracks app space update information.""" description: Optional[str] = None resources: Optional[List[AppResource]] = None status: Optional[SpaceUpdateStatus] = None usage_policy_id: Optional[str] = None user_api_scopes: Optional[List[str]] = None def as_dict(self) -> dict: """Serializes the SpaceUpdate into a dictionary suitable for use as a JSON request body.""" body = {} if self.description is not None: body["description"] = self.description if self.resources: body["resources"] = [v.as_dict() for v in self.resources] if self.status: body["status"] = self.status.as_dict() if self.usage_policy_id is not None: body["usage_policy_id"] = self.usage_policy_id if self.user_api_scopes: body["user_api_scopes"] = [v for v in self.user_api_scopes] return body def as_shallow_dict(self) -> dict: """Serializes the SpaceUpdate into a shallow dictionary of its immediate attributes.""" body = {} if self.description is not None: body["description"] = self.description if self.resources: body["resources"] = self.resources if self.status: body["status"] = self.status if self.usage_policy_id is not None: body["usage_policy_id"] = self.usage_policy_id if self.user_api_scopes: body["user_api_scopes"] = self.user_api_scopes return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> SpaceUpdate: """Deserializes the SpaceUpdate from a dictionary.""" return cls( description=d.get("description", None), resources=_repeated_dict(d, "resources", AppResource), status=_from_dict(d, "status", SpaceUpdateStatus), usage_policy_id=d.get("usage_policy_id", None), user_api_scopes=d.get("user_api_scopes", None), ) class SpaceUpdateState(Enum): FAILED = "FAILED" IN_PROGRESS = "IN_PROGRESS" NOT_UPDATED = "NOT_UPDATED" SUCCEEDED = "SUCCEEDED" @dataclass class SpaceUpdateStatus: """Status of an app space update operation""" message: Optional[str] = None state: Optional[SpaceUpdateState] = None def as_dict(self) -> dict: """Serializes the SpaceUpdateStatus into a dictionary suitable for use as a JSON request body.""" body = {} if self.message is not None: body["message"] = self.message if self.state is not None: body["state"] = self.state.value return body def as_shallow_dict(self) -> dict: """Serializes the SpaceUpdateStatus into a shallow dictionary of its immediate attributes.""" body = {} if self.message is not None: body["message"] = self.message if self.state is not None: body["state"] = self.state return body @classmethod def from_dict(cls, d: Dict[str, Any]) -> SpaceUpdateStatus: """Deserializes the SpaceUpdateStatus from a dictionary.""" return cls(message=d.get("message", None), state=_enum(d, "state", SpaceUpdateState)) class AppsAPI: """Apps run directly on a customer's Databricks instance, integrate with their data, use and extend Databricks services, and enable users to interact through single sign-on.""" def __init__(self, api_client): self._api = api_client def wait_get_app_active( self, name: str, timeout=timedelta(minutes=20), callback: Optional[Callable[[App], None]] = None ) -> App: deadline = time.time() + timeout.total_seconds() target_states = (ComputeState.ACTIVE,) failure_states = ( ComputeState.ERROR, ComputeState.STOPPED, ) status_message = "polling..." attempt = 1 while time.time() < deadline: poll = self.get(name=name) status = poll.compute_status.state status_message = f"current status: {status}" if poll.compute_status: status_message = poll.compute_status.message if status in target_states: return poll if callback: callback(poll) if status in failure_states: msg = f"failed to reach ACTIVE, got {status}: {status_message}" raise OperationFailed(msg) prefix = f"name={name}" sleep = attempt if sleep > 10: # sleep 10s max per attempt sleep = 10 _LOG.debug(f"{prefix}: ({status}) {status_message} (sleeping ~{sleep}s)") time.sleep(sleep + random.random()) attempt += 1 raise TimeoutError(f"timed out after {timeout}: {status_message}") def wait_get_update_app_succeeded( self, app_name: str, timeout=timedelta(minutes=20), callback: Optional[Callable[[AppUpdate], None]] = None ) -> AppUpdate: deadline = time.time() + timeout.total_seconds() target_states = (AppUpdateUpdateStatusUpdateState.SUCCEEDED,) failure_states = (AppUpdateUpdateStatusUpdateState.FAILED,) status_message = "polling..." attempt = 1 while time.time() < deadline: poll = self.get_update(app_name=app_name) status = poll.status.state status_message = f"current status: {status}" if poll.status: status_message = poll.status.message if status in target_states: return poll if callback: callback(poll) if status in failure_states: msg = f"failed to reach SUCCEEDED, got {status}: {status_message}" raise OperationFailed(msg) prefix = f"app_name={app_name}" sleep = attempt if sleep > 10: # sleep 10s max per attempt sleep = 10 _LOG.debug(f"{prefix}: ({status}) {status_message} (sleeping ~{sleep}s)") time.sleep(sleep + random.random()) attempt += 1 raise TimeoutError(f"timed out after {timeout}: {status_message}") def wait_get_deployment_app_succeeded( self, app_name: str, deployment_id: str, timeout=timedelta(minutes=20), callback: Optional[Callable[[AppDeployment], None]] = None, ) -> AppDeployment: deadline = time.time() + timeout.total_seconds() target_states = (AppDeploymentState.SUCCEEDED,) failure_states = (AppDeploymentState.FAILED,) status_message = "polling..." attempt = 1 while time.time() < deadline: poll = self.get_deployment(app_name=app_name, deployment_id=deployment_id) status = poll.status.state status_message = f"current status: {status}" if poll.status: status_message = poll.status.message if status in target_states: return poll if callback: callback(poll) if status in failure_states: msg = f"failed to reach SUCCEEDED, got {status}: {status_message}" raise OperationFailed(msg) prefix = f"app_name={app_name}, deployment_id={deployment_id}" sleep = attempt if sleep > 10: # sleep 10s max per attempt sleep = 10 _LOG.debug(f"{prefix}: ({status}) {status_message} (sleeping ~{sleep}s)") time.sleep(sleep + random.random()) attempt += 1 raise TimeoutError(f"timed out after {timeout}: {status_message}") def wait_get_app_stopped( self, name: str, timeout=timedelta(minutes=20), callback: Optional[Callable[[App], None]] = None ) -> App: deadline = time.time() + timeout.total_seconds() target_states = (ComputeState.STOPPED,) failure_states = (ComputeState.ERROR,) status_message = "polling..." attempt = 1 while time.time() < deadline: poll = self.get(name=name) status = poll.compute_status.state status_message = f"current status: {status}" if poll.compute_status: status_message = poll.compute_status.message if status in target_states: return poll if callback: callback(poll) if status in failure_states: msg = f"failed to reach STOPPED, got {status}: {status_message}" raise OperationFailed(msg) prefix = f"name={name}" sleep = attempt if sleep > 10: # sleep 10s max per attempt sleep = 10 _LOG.debug(f"{prefix}: ({status}) {status_message} (sleeping ~{sleep}s)") time.sleep(sleep + random.random()) attempt += 1 raise TimeoutError(f"timed out after {timeout}: {status_message}") def create(self, app: App, *, no_compute: Optional[bool] = None) -> Wait[App]: """Creates a new app. :param app: :class:`App` :param no_compute: bool (optional) If true, the app will not be started after creation. :returns: Long-running operation waiter for :class:`App`. See :method:wait_get_app_active for more details. """ body = app.as_dict() query = {} if no_compute is not None: query["no_compute"] = no_compute headers = { "Accept": "application/json", "Content-Type": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id op_response = self._api.do("POST", "/api/2.0/apps", query=query, body=body, headers=headers) return Wait(self.wait_get_app_active, response=App.from_dict(op_response), name=op_response["name"]) def create_and_wait(self, app: App, *, no_compute: Optional[bool] = None, timeout=timedelta(minutes=20)) -> App: return self.create(app=app, no_compute=no_compute).result(timeout=timeout) def create_space(self, space: Space) -> CreateSpaceOperation: """Creates a new app space. :param space: :class:`Space` :returns: :class:`Operation` """ body = space.as_dict() headers = { "Accept": "application/json", "Content-Type": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("POST", "/api/2.0/app-spaces", body=body, headers=headers) operation = Operation.from_dict(res) return CreateSpaceOperation(self, operation) def create_update(self, app_name: str, update_mask: str, *, app: Optional[App] = None) -> Wait[AppUpdate]: """Creates an app update and starts the update process. The update process is asynchronous and the status of the update can be checked with the GetAppUpdate method. :param app_name: str :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. :param app: :class:`App` (optional) :returns: Long-running operation waiter for :class:`AppUpdate`. See :method:wait_get_update_app_succeeded for more details. """ body = {} if app is not None: body["app"] = app.as_dict() if update_mask is not None: body["update_mask"] = update_mask headers = { "Accept": "application/json", "Content-Type": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id op_response = self._api.do("POST", f"/api/2.0/apps/{app_name}/update", body=body, headers=headers) return Wait(self.wait_get_update_app_succeeded, response=AppUpdate.from_dict(op_response), app_name=app_name) def create_update_and_wait( self, app_name: str, update_mask: str, *, app: Optional[App] = None, timeout=timedelta(minutes=20) ) -> AppUpdate: return self.create_update(app=app, app_name=app_name, update_mask=update_mask).result(timeout=timeout) def delete(self, name: str) -> App: """Deletes an app. :param name: str The name of the app. :returns: :class:`App` """ headers = { "Accept": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("DELETE", f"/api/2.0/apps/{name}", headers=headers) return App.from_dict(res) def delete_space(self, name: str) -> DeleteSpaceOperation: """Deletes an app space. :param name: str The name of the app space. :returns: :class:`Operation` """ headers = { "Accept": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("DELETE", f"/api/2.0/app-spaces/{name}", headers=headers) operation = Operation.from_dict(res) return DeleteSpaceOperation(self, operation) def deploy(self, app_name: str, app_deployment: AppDeployment) -> Wait[AppDeployment]: """Creates an app deployment for the app with the supplied name. :param app_name: str The name of the app. :param app_deployment: :class:`AppDeployment` The app deployment configuration. :returns: Long-running operation waiter for :class:`AppDeployment`. See :method:wait_get_deployment_app_succeeded for more details. """ body = app_deployment.as_dict() headers = { "Accept": "application/json", "Content-Type": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id op_response = self._api.do("POST", f"/api/2.0/apps/{app_name}/deployments", body=body, headers=headers) return Wait( self.wait_get_deployment_app_succeeded, response=AppDeployment.from_dict(op_response), app_name=app_name, deployment_id=op_response["deployment_id"], ) def deploy_and_wait( self, app_name: str, app_deployment: AppDeployment, timeout=timedelta(minutes=20) ) -> AppDeployment: return self.deploy(app_deployment=app_deployment, app_name=app_name).result(timeout=timeout) def get(self, name: str) -> App: """Retrieves information for the app with the supplied name. :param name: str The name of the app. :returns: :class:`App` """ headers = { "Accept": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("GET", f"/api/2.0/apps/{name}", headers=headers) return App.from_dict(res) def get_deployment(self, app_name: str, deployment_id: str) -> AppDeployment: """Retrieves information for the app deployment with the supplied name and deployment id. :param app_name: str The name of the app. :param deployment_id: str The unique id of the deployment. :returns: :class:`AppDeployment` """ headers = { "Accept": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("GET", f"/api/2.0/apps/{app_name}/deployments/{deployment_id}", headers=headers) return AppDeployment.from_dict(res) def get_permission_levels(self, app_name: str) -> GetAppPermissionLevelsResponse: """Gets the permission levels that a user can have on an object. :param app_name: str The app for which to get or manage permissions. :returns: :class:`GetAppPermissionLevelsResponse` """ headers = { "Accept": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("GET", f"/api/2.0/permissions/apps/{app_name}/permissionLevels", headers=headers) return GetAppPermissionLevelsResponse.from_dict(res) def get_permissions(self, app_name: str) -> AppPermissions: """Gets the permissions of an app. Apps can inherit permissions from their root object. :param app_name: str The app for which to get or manage permissions. :returns: :class:`AppPermissions` """ headers = { "Accept": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("GET", f"/api/2.0/permissions/apps/{app_name}", headers=headers) return AppPermissions.from_dict(res) def get_space(self, name: str) -> Space: """Retrieves information for the app space with the supplied name. :param name: str The name of the app space. :returns: :class:`Space` """ headers = { "Accept": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("GET", f"/api/2.0/app-spaces/{name}", headers=headers) return Space.from_dict(res) def get_space_operation(self, name: str) -> Operation: """Gets the status of an app space update operation. :param name: str The name of the operation resource. :returns: :class:`Operation` """ headers = { "Accept": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("GET", f"/api/2.0/app-spaces/{name}/operation", headers=headers) return Operation.from_dict(res) def get_update(self, app_name: str) -> AppUpdate: """Gets the status of an app update. :param app_name: str The name of the app. :returns: :class:`AppUpdate` """ headers = { "Accept": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("GET", f"/api/2.0/apps/{app_name}/update", headers=headers) return AppUpdate.from_dict(res) def list( self, *, page_size: Optional[int] = None, page_token: Optional[str] = None, space: Optional[str] = None ) -> Iterator[App]: """Lists all apps in the workspace. :param page_size: int (optional) Upper bound for items returned. :param page_token: str (optional) Pagination token to go to the next page of apps. Requests first page if absent. :param space: str (optional) Filter apps by app space name. When specified, only apps belonging to this space are returned. :returns: Iterator over :class:`App` """ query = {} if page_size is not None: query["page_size"] = page_size if page_token is not None: query["page_token"] = page_token if space is not None: query["space"] = space headers = { "Accept": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id while True: json = self._api.do("GET", "/api/2.0/apps", query=query, headers=headers) if "apps" in json: for v in json["apps"]: yield App.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 list_deployments( self, app_name: str, *, page_size: Optional[int] = None, page_token: Optional[str] = None ) -> Iterator[AppDeployment]: """Lists all app deployments for the app with the supplied name. :param app_name: str The name of the app. :param page_size: int (optional) Upper bound for items returned. :param page_token: str (optional) Pagination token to go to the next page of apps. Requests first page if absent. :returns: Iterator over :class:`AppDeployment` """ 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", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id while True: json = self._api.do("GET", f"/api/2.0/apps/{app_name}/deployments", query=query, headers=headers) if "app_deployments" in json: for v in json["app_deployments"]: yield AppDeployment.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 list_spaces(self, *, page_size: Optional[int] = None, page_token: Optional[str] = None) -> Iterator[Space]: """Lists all app spaces in the workspace. :param page_size: int (optional) Upper bound for items returned. :param page_token: str (optional) Pagination token to go to the next page of app spaces. Requests first page if absent. :returns: Iterator over :class:`Space` """ 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", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id while True: json = self._api.do("GET", "/api/2.0/app-spaces", query=query, headers=headers) if "spaces" in json: for v in json["spaces"]: yield Space.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 set_permissions( self, app_name: str, *, access_control_list: Optional[List[AppAccessControlRequest]] = None ) -> AppPermissions: """Sets permissions on an object, replacing existing permissions if they exist. Deletes all direct permissions if none are specified. Objects can inherit permissions from their root object. :param app_name: str The app for which to get or manage permissions. :param access_control_list: List[:class:`AppAccessControlRequest`] (optional) :returns: :class:`AppPermissions` """ body = {} if access_control_list is not None: body["access_control_list"] = [v.as_dict() for v in access_control_list] headers = { "Accept": "application/json", "Content-Type": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("PUT", f"/api/2.0/permissions/apps/{app_name}", body=body, headers=headers) return AppPermissions.from_dict(res) def start(self, name: str) -> Wait[App]: """Start the last active deployment of the app in the workspace. :param name: str The name of the app. :returns: Long-running operation waiter for :class:`App`. See :method:wait_get_app_active for more details. """ headers = { "Accept": "application/json", "Content-Type": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id op_response = self._api.do("POST", f"/api/2.0/apps/{name}/start", headers=headers) return Wait(self.wait_get_app_active, response=App.from_dict(op_response), name=op_response["name"]) def start_and_wait(self, name: str, timeout=timedelta(minutes=20)) -> App: return self.start(name=name).result(timeout=timeout) def stop(self, name: str) -> Wait[App]: """Stops the active deployment of the app in the workspace. :param name: str The name of the app. :returns: Long-running operation waiter for :class:`App`. See :method:wait_get_app_stopped for more details. """ headers = { "Accept": "application/json", "Content-Type": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id op_response = self._api.do("POST", f"/api/2.0/apps/{name}/stop", headers=headers) return Wait(self.wait_get_app_stopped, response=App.from_dict(op_response), name=op_response["name"]) def stop_and_wait(self, name: str, timeout=timedelta(minutes=20)) -> App: return self.stop(name=name).result(timeout=timeout) def update(self, name: str, app: App) -> App: """Updates the app with the supplied name. :param name: str The name of the app. The name must contain only lowercase alphanumeric characters and hyphens. It must be unique within the workspace. :param app: :class:`App` :returns: :class:`App` """ body = app.as_dict() headers = { "Accept": "application/json", "Content-Type": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("PATCH", f"/api/2.0/apps/{name}", body=body, headers=headers) return App.from_dict(res) def update_permissions( self, app_name: str, *, access_control_list: Optional[List[AppAccessControlRequest]] = None ) -> AppPermissions: """Updates the permissions on an app. Apps can inherit permissions from their root object. :param app_name: str The app for which to get or manage permissions. :param access_control_list: List[:class:`AppAccessControlRequest`] (optional) :returns: :class:`AppPermissions` """ body = {} if access_control_list is not None: body["access_control_list"] = [v.as_dict() for v in access_control_list] headers = { "Accept": "application/json", "Content-Type": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("PATCH", f"/api/2.0/permissions/apps/{app_name}", body=body, headers=headers) return AppPermissions.from_dict(res) def update_space(self, name: str, space: Space, update_mask: FieldMask) -> UpdateSpaceOperation: """Updates an app space. The update process is asynchronous and the status of the update can be checked with the GetSpaceOperation method. :param name: str The name of the app space. The name must contain only lowercase alphanumeric characters and hyphens. It must be unique within the workspace. :param space: :class:`Space` :param update_mask: FieldMask 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:`Operation` """ body = space.as_dict() query = {} if update_mask is not None: query["update_mask"] = update_mask.ToJsonString() headers = { "Accept": "application/json", "Content-Type": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("PATCH", f"/api/2.0/app-spaces/{name}", query=query, body=body, headers=headers) operation = Operation.from_dict(res) return UpdateSpaceOperation(self, operation) class CreateSpaceOperation: """Long-running operation for create_space""" def __init__(self, impl: AppsAPI, operation: Operation): self._impl = impl self._operation = operation def wait(self, opts: Optional[lro.LroOptions] = None) -> Space: """Wait blocks until the long-running operation is completed. If no timeout is specified, this will poll indefinitely. If a timeout is provided and the operation didn't finish within the timeout, this function will raise an error of type TimeoutError, otherwise returns successful response and any errors encountered. :param opts: :class:`LroOptions` Timeout options (default: polls indefinitely) :returns: :class:`Space` """ def poll_operation(): operation = self._impl.get_space_operation(name=self._operation.name) # Update local operation state self._operation = operation if not operation.done: return None, RetryError.continues("operation still in progress") if operation.error: error_msg = operation.error.message if operation.error.message else "unknown error" if operation.error.error_code: error_msg = f"[{operation.error.error_code}] {error_msg}" return None, RetryError.halt(Exception(f"operation failed: {error_msg}")) # Operation completed successfully, unmarshal response. if operation.response is None: return None, RetryError.halt(Exception("operation completed but no response available")) space = Space.from_dict(operation.response) return space, None return poll(poll_operation, timeout=opts.timeout if opts is not None else None) def name(self) -> str: """Name returns the name of the long-running operation. The name is assigned by the server and is unique within the service from which the operation is created. :returns: str """ return self._operation.name def metadata(self) -> Space: """Metadata returns metadata associated with the long-running operation. If the metadata is not available, the returned metadata is None. :returns: :class:`Space` or None """ if self._operation.metadata is None: return None return Space.from_dict(self._operation.metadata) def done(self) -> bool: """Done reports whether the long-running operation has completed. :returns: bool """ # Refresh the operation state first operation = self._impl.get_space_operation(name=self._operation.name) # Update local operation state self._operation = operation return operation.done class DeleteSpaceOperation: """Long-running operation for delete_space""" def __init__(self, impl: AppsAPI, operation: Operation): self._impl = impl self._operation = operation def wait(self, opts: Optional[lro.LroOptions] = None): """Wait blocks until the long-running operation is completed. If no timeout is specified, this will poll indefinitely. If a timeout is provided and the operation didn't finish within the timeout, this function will raise an error of type TimeoutError, otherwise returns successful response and any errors encountered. :param opts: :class:`LroOptions` Timeout options (default: polls indefinitely) :returns: :class:`Any /* MISSING TYPE */` """ def poll_operation(): operation = self._impl.get_space_operation(name=self._operation.name) # Update local operation state self._operation = operation if not operation.done: return None, RetryError.continues("operation still in progress") if operation.error: error_msg = operation.error.message if operation.error.message else "unknown error" if operation.error.error_code: error_msg = f"[{operation.error.error_code}] {error_msg}" return None, RetryError.halt(Exception(f"operation failed: {error_msg}")) # Operation completed successfully, unmarshal response. if operation.response is None: return None, RetryError.halt(Exception("operation completed but no response available")) return {}, None poll(poll_operation, timeout=opts.timeout if opts is not None else None) def name(self) -> str: """Name returns the name of the long-running operation. The name is assigned by the server and is unique within the service from which the operation is created. :returns: str """ return self._operation.name def metadata(self) -> Space: """Metadata returns metadata associated with the long-running operation. If the metadata is not available, the returned metadata is None. :returns: :class:`Space` or None """ if self._operation.metadata is None: return None return Space.from_dict(self._operation.metadata) def done(self) -> bool: """Done reports whether the long-running operation has completed. :returns: bool """ # Refresh the operation state first operation = self._impl.get_space_operation(name=self._operation.name) # Update local operation state self._operation = operation return operation.done class UpdateSpaceOperation: """Long-running operation for update_space""" def __init__(self, impl: AppsAPI, operation: Operation): self._impl = impl self._operation = operation def wait(self, opts: Optional[lro.LroOptions] = None) -> Space: """Wait blocks until the long-running operation is completed. If no timeout is specified, this will poll indefinitely. If a timeout is provided and the operation didn't finish within the timeout, this function will raise an error of type TimeoutError, otherwise returns successful response and any errors encountered. :param opts: :class:`LroOptions` Timeout options (default: polls indefinitely) :returns: :class:`Space` """ def poll_operation(): operation = self._impl.get_space_operation(name=self._operation.name) # Update local operation state self._operation = operation if not operation.done: return None, RetryError.continues("operation still in progress") if operation.error: error_msg = operation.error.message if operation.error.message else "unknown error" if operation.error.error_code: error_msg = f"[{operation.error.error_code}] {error_msg}" return None, RetryError.halt(Exception(f"operation failed: {error_msg}")) # Operation completed successfully, unmarshal response. if operation.response is None: return None, RetryError.halt(Exception("operation completed but no response available")) space = Space.from_dict(operation.response) return space, None return poll(poll_operation, timeout=opts.timeout if opts is not None else None) def name(self) -> str: """Name returns the name of the long-running operation. The name is assigned by the server and is unique within the service from which the operation is created. :returns: str """ return self._operation.name def metadata(self) -> SpaceUpdate: """Metadata returns metadata associated with the long-running operation. If the metadata is not available, the returned metadata is None. :returns: :class:`SpaceUpdate` or None """ if self._operation.metadata is None: return None return SpaceUpdate.from_dict(self._operation.metadata) def done(self) -> bool: """Done reports whether the long-running operation has completed. :returns: bool """ # Refresh the operation state first operation = self._impl.get_space_operation(name=self._operation.name) # Update local operation state self._operation = operation return operation.done class AppsSettingsAPI: """Apps Settings manage the settings for the Apps service on a customer's Databricks instance.""" def __init__(self, api_client): self._api = api_client def create_custom_template(self, template: CustomTemplate) -> CustomTemplate: """Creates a custom template. :param template: :class:`CustomTemplate` :returns: :class:`CustomTemplate` """ body = template.as_dict() headers = { "Accept": "application/json", "Content-Type": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("POST", "/api/2.0/apps-settings/templates", body=body, headers=headers) return CustomTemplate.from_dict(res) def delete_custom_template(self, name: str) -> CustomTemplate: """Deletes the custom template with the specified name. :param name: str The name of the custom template. :returns: :class:`CustomTemplate` """ headers = { "Accept": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("DELETE", f"/api/2.0/apps-settings/templates/{name}", headers=headers) return CustomTemplate.from_dict(res) def get_custom_template(self, name: str) -> CustomTemplate: """Gets the custom template with the specified name. :param name: str The name of the custom template. :returns: :class:`CustomTemplate` """ headers = { "Accept": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("GET", f"/api/2.0/apps-settings/templates/{name}", headers=headers) return CustomTemplate.from_dict(res) def list_custom_templates( self, *, page_size: Optional[int] = None, page_token: Optional[str] = None ) -> Iterator[CustomTemplate]: """Lists all custom templates in the workspace. :param page_size: int (optional) Upper bound for items returned. :param page_token: str (optional) Pagination token to go to the next page of custom templates. Requests first page if absent. :returns: Iterator over :class:`CustomTemplate` """ 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", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id while True: json = self._api.do("GET", "/api/2.0/apps-settings/templates", query=query, headers=headers) if "templates" in json: for v in json["templates"]: yield CustomTemplate.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_custom_template(self, name: str, template: CustomTemplate) -> CustomTemplate: """Updates the custom template with the specified name. Note that the template name cannot be updated. :param name: str The name of the template. It must contain only alphanumeric characters, hyphens, underscores, and whitespaces. It must be unique within the workspace. :param template: :class:`CustomTemplate` :returns: :class:`CustomTemplate` """ body = template.as_dict() headers = { "Accept": "application/json", "Content-Type": "application/json", } cfg = self._api._cfg if cfg.host_type == HostType.UNIFIED and cfg.workspace_id: headers["X-Databricks-Org-Id"] = cfg.workspace_id res = self._api.do("PUT", f"/api/2.0/apps-settings/templates/{name}", body=body, headers=headers) return CustomTemplate.from_dict(res)