From a851bc8b9baa8d76450f76256d3543331e685341 Mon Sep 17 00:00:00 2001 From: Miles Yucht Date: Mon, 7 Aug 2023 09:48:27 +0200 Subject: [PATCH] Update OpenAPI Spec for 7 Aug 2023 --- .codegen/_openapi_sha | 2 +- databricks/sdk/service/compute.py | 753 ++++++++++++++++++++++++ databricks/sdk/service/iam.py | 316 +++++++++- databricks/sdk/service/jobs.py | 244 ++++++++ databricks/sdk/service/ml.py | 509 ++++++++++++++++ databricks/sdk/service/oauth2.py | 8 + databricks/sdk/service/pipelines.py | 247 ++++++++ databricks/sdk/service/provisioning.py | 37 ++ databricks/sdk/service/serving.py | 265 +++++++++ databricks/sdk/service/settings.py | 206 +++++++ databricks/sdk/service/sql.py | 304 +++++++++- databricks/sdk/service/workspace.py | 528 +++++++++++++++++ docs/account/custom_app_integration.rst | 5 +- docs/account/workspaces.rst | 23 +- docs/workspace/cluster_policies.rst | 52 ++ docs/workspace/clusters.rst | 50 ++ docs/workspace/experiments.rst | 50 ++ docs/workspace/instance_pools.rst | 52 ++ docs/workspace/jobs.rst | 50 ++ docs/workspace/model_registry.rst | 53 ++ docs/workspace/permissions.rst | 63 +- docs/workspace/pipelines.rst | 50 ++ docs/workspace/repos.rst | 50 ++ docs/workspace/serving_endpoints.rst | 53 ++ docs/workspace/token_management.rst | 40 ++ docs/workspace/users.rst | 40 ++ docs/workspace/warehouses.rst | 52 ++ docs/workspace/workspace.rst | 61 ++ 28 files changed, 4109 insertions(+), 54 deletions(-) diff --git a/.codegen/_openapi_sha b/.codegen/_openapi_sha index 4800af05..202e5766 100644 --- a/.codegen/_openapi_sha +++ b/.codegen/_openapi_sha @@ -1 +1 @@ -a1b6c1ecfaab6635911d3c060a8dd797ac6b2d4d \ No newline at end of file +386b65ecdc825b9c3ed4aa7ca88e2e5baf9d87df \ No newline at end of file diff --git a/databricks/sdk/service/compute.py b/databricks/sdk/service/compute.py index 25ecc406..de2605a2 100755 --- a/databricks/sdk/service/compute.py +++ b/databricks/sdk/service/compute.py @@ -213,6 +213,57 @@ class CloudProviderNodeStatus(Enum): NOT_ENABLED_ON_SUBSCRIPTION = 'NotEnabledOnSubscription' +@dataclass +class ClusterAccessControlRequest: + group_name: Optional[str] = None + permission_level: Optional['ClusterPermissionLevel'] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ClusterAccessControlRequest': + return cls(group_name=d.get('group_name', None), + permission_level=_enum(d, 'permission_level', ClusterPermissionLevel), + service_principal_name=d.get('service_principal_name', None), + user_name=d.get('user_name', None)) + + +@dataclass +class ClusterAccessControlResponse: + all_permissions: Optional['List[ClusterPermission]'] = None + display_name: Optional[str] = None + group_name: Optional[str] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ClusterAccessControlResponse': + return cls(all_permissions=_repeated(d, 'all_permissions', ClusterPermission), + 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 ClusterAttributes: spark_version: str @@ -508,6 +559,224 @@ def from_dict(cls, d: Dict[str, any]) -> 'ClusterLogConf': return cls(dbfs=_from_dict(d, 'dbfs', DbfsStorageInfo), s3=_from_dict(d, 's3', S3StorageInfo)) +@dataclass +class ClusterPermission: + inherited: Optional[bool] = None + inherited_from_object: Optional['List[str]'] = None + permission_level: Optional['ClusterPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ClusterPermission': + return cls(inherited=d.get('inherited', None), + inherited_from_object=d.get('inherited_from_object', None), + permission_level=_enum(d, 'permission_level', ClusterPermissionLevel)) + + +class ClusterPermissionLevel(Enum): + """Permission level""" + + CAN_ATTACH_TO = 'CAN_ATTACH_TO' + CAN_MANAGE = 'CAN_MANAGE' + CAN_RESTART = 'CAN_RESTART' + + +@dataclass +class ClusterPermissions: + access_control_list: Optional['List[ClusterAccessControlResponse]'] = None + object_id: Optional[str] = None + object_type: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ClusterPermissions': + return cls(access_control_list=_repeated(d, 'access_control_list', ClusterAccessControlResponse), + object_id=d.get('object_id', None), + object_type=d.get('object_type', None)) + + +@dataclass +class ClusterPermissionsDescription: + description: Optional[str] = None + permission_level: Optional['ClusterPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ClusterPermissionsDescription': + return cls(description=d.get('description', None), + permission_level=_enum(d, 'permission_level', ClusterPermissionLevel)) + + +@dataclass +class ClusterPermissionsRequest: + access_control_list: Optional['List[ClusterAccessControlRequest]'] = None + cluster_id: Optional[str] = None + + def as_dict(self) -> dict: + body = {} + if self.access_control_list: + body['access_control_list'] = [v.as_dict() for v in self.access_control_list] + if self.cluster_id is not None: body['cluster_id'] = self.cluster_id + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ClusterPermissionsRequest': + return cls(access_control_list=_repeated(d, 'access_control_list', ClusterAccessControlRequest), + cluster_id=d.get('cluster_id', None)) + + +@dataclass +class ClusterPolicyAccessControlRequest: + group_name: Optional[str] = None + permission_level: Optional['ClusterPolicyPermissionLevel'] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ClusterPolicyAccessControlRequest': + return cls(group_name=d.get('group_name', None), + permission_level=_enum(d, 'permission_level', ClusterPolicyPermissionLevel), + service_principal_name=d.get('service_principal_name', None), + user_name=d.get('user_name', None)) + + +@dataclass +class ClusterPolicyAccessControlResponse: + all_permissions: Optional['List[ClusterPolicyPermission]'] = None + display_name: Optional[str] = None + group_name: Optional[str] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ClusterPolicyAccessControlResponse': + return cls(all_permissions=_repeated(d, 'all_permissions', ClusterPolicyPermission), + 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 ClusterPolicyPermission: + inherited: Optional[bool] = None + inherited_from_object: Optional['List[str]'] = None + permission_level: Optional['ClusterPolicyPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ClusterPolicyPermission': + return cls(inherited=d.get('inherited', None), + inherited_from_object=d.get('inherited_from_object', None), + permission_level=_enum(d, 'permission_level', ClusterPolicyPermissionLevel)) + + +class ClusterPolicyPermissionLevel(Enum): + """Permission level""" + + CAN_USE = 'CAN_USE' + + +@dataclass +class ClusterPolicyPermissions: + access_control_list: Optional['List[ClusterPolicyAccessControlResponse]'] = None + object_id: Optional[str] = None + object_type: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ClusterPolicyPermissions': + return cls(access_control_list=_repeated(d, 'access_control_list', + ClusterPolicyAccessControlResponse), + object_id=d.get('object_id', None), + object_type=d.get('object_type', None)) + + +@dataclass +class ClusterPolicyPermissionsDescription: + description: Optional[str] = None + permission_level: Optional['ClusterPolicyPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ClusterPolicyPermissionsDescription': + return cls(description=d.get('description', None), + permission_level=_enum(d, 'permission_level', ClusterPolicyPermissionLevel)) + + +@dataclass +class ClusterPolicyPermissionsRequest: + access_control_list: Optional['List[ClusterPolicyAccessControlRequest]'] = None + cluster_policy_id: Optional[str] = None + + def as_dict(self) -> dict: + body = {} + if self.access_control_list: + body['access_control_list'] = [v.as_dict() for v in self.access_control_list] + if self.cluster_policy_id is not None: body['cluster_policy_id'] = self.cluster_policy_id + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ClusterPolicyPermissionsRequest': + return cls(access_control_list=_repeated(d, 'access_control_list', ClusterPolicyAccessControlRequest), + cluster_policy_id=d.get('cluster_policy_id', None)) + + @dataclass class ClusterSize: autoscale: Optional['AutoScale'] = None @@ -1651,6 +1920,62 @@ class GcpAvailability(Enum): PREEMPTIBLE_WITH_FALLBACK_GCP = 'PREEMPTIBLE_WITH_FALLBACK_GCP' +@dataclass +class GetClusterPermissionLevelsRequest: + """Get cluster permission levels""" + + cluster_id: str + + +@dataclass +class GetClusterPermissionLevelsResponse: + permission_levels: Optional['List[ClusterPermissionsDescription]'] = None + + def as_dict(self) -> dict: + body = {} + if self.permission_levels: body['permission_levels'] = [v.as_dict() for v in self.permission_levels] + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'GetClusterPermissionLevelsResponse': + return cls(permission_levels=_repeated(d, 'permission_levels', ClusterPermissionsDescription)) + + +@dataclass +class GetClusterPermissionsRequest: + """Get cluster permissions""" + + cluster_id: str + + +@dataclass +class GetClusterPolicyPermissionLevelsRequest: + """Get cluster policy permission levels""" + + cluster_policy_id: str + + +@dataclass +class GetClusterPolicyPermissionLevelsResponse: + permission_levels: Optional['List[ClusterPolicyPermissionsDescription]'] = None + + def as_dict(self) -> dict: + body = {} + if self.permission_levels: body['permission_levels'] = [v.as_dict() for v in self.permission_levels] + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'GetClusterPolicyPermissionLevelsResponse': + return cls(permission_levels=_repeated(d, 'permission_levels', ClusterPolicyPermissionsDescription)) + + +@dataclass +class GetClusterPolicyPermissionsRequest: + """Get cluster policy permissions""" + + cluster_policy_id: str + + @dataclass class GetClusterPolicyRequest: """Get entity""" @@ -1804,6 +2129,34 @@ def from_dict(cls, d: Dict[str, any]) -> 'GetInstancePool': status=_from_dict(d, 'status', InstancePoolStatus)) +@dataclass +class GetInstancePoolPermissionLevelsRequest: + """Get instance pool permission levels""" + + instance_pool_id: str + + +@dataclass +class GetInstancePoolPermissionLevelsResponse: + permission_levels: Optional['List[InstancePoolPermissionsDescription]'] = None + + def as_dict(self) -> dict: + body = {} + if self.permission_levels: body['permission_levels'] = [v.as_dict() for v in self.permission_levels] + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'GetInstancePoolPermissionLevelsResponse': + return cls(permission_levels=_repeated(d, 'permission_levels', InstancePoolPermissionsDescription)) + + +@dataclass +class GetInstancePoolPermissionsRequest: + """Get instance pool permissions""" + + instance_pool_id: str + + @dataclass class GetInstancePoolRequest: """Get instance pool information""" @@ -1990,6 +2343,57 @@ def from_dict(cls, d: Dict[str, any]) -> 'InstallLibraries': return cls(cluster_id=d.get('cluster_id', None), libraries=_repeated(d, 'libraries', Library)) +@dataclass +class InstancePoolAccessControlRequest: + group_name: Optional[str] = None + permission_level: Optional['InstancePoolPermissionLevel'] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'InstancePoolAccessControlRequest': + return cls(group_name=d.get('group_name', None), + permission_level=_enum(d, 'permission_level', InstancePoolPermissionLevel), + service_principal_name=d.get('service_principal_name', None), + user_name=d.get('user_name', None)) + + +@dataclass +class InstancePoolAccessControlResponse: + all_permissions: Optional['List[InstancePoolPermission]'] = None + display_name: Optional[str] = None + group_name: Optional[str] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'InstancePoolAccessControlResponse': + return cls(all_permissions=_repeated(d, 'all_permissions', InstancePoolPermission), + 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 InstancePoolAndStats: aws_attributes: Optional['InstancePoolAwsAttributes'] = None @@ -2160,6 +2564,89 @@ def from_dict(cls, d: Dict[str, any]) -> 'InstancePoolGcpAttributes': local_ssd_count=d.get('local_ssd_count', None)) +@dataclass +class InstancePoolPermission: + inherited: Optional[bool] = None + inherited_from_object: Optional['List[str]'] = None + permission_level: Optional['InstancePoolPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'InstancePoolPermission': + return cls(inherited=d.get('inherited', None), + inherited_from_object=d.get('inherited_from_object', None), + permission_level=_enum(d, 'permission_level', InstancePoolPermissionLevel)) + + +class InstancePoolPermissionLevel(Enum): + """Permission level""" + + CAN_ATTACH_TO = 'CAN_ATTACH_TO' + CAN_MANAGE = 'CAN_MANAGE' + + +@dataclass +class InstancePoolPermissions: + access_control_list: Optional['List[InstancePoolAccessControlResponse]'] = None + object_id: Optional[str] = None + object_type: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'InstancePoolPermissions': + return cls(access_control_list=_repeated(d, 'access_control_list', InstancePoolAccessControlResponse), + object_id=d.get('object_id', None), + object_type=d.get('object_type', None)) + + +@dataclass +class InstancePoolPermissionsDescription: + description: Optional[str] = None + permission_level: Optional['InstancePoolPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'InstancePoolPermissionsDescription': + return cls(description=d.get('description', None), + permission_level=_enum(d, 'permission_level', InstancePoolPermissionLevel)) + + +@dataclass +class InstancePoolPermissionsRequest: + access_control_list: Optional['List[InstancePoolAccessControlRequest]'] = None + instance_pool_id: Optional[str] = None + + def as_dict(self) -> dict: + body = {} + if self.access_control_list: + body['access_control_list'] = [v.as_dict() for v in self.access_control_list] + if self.instance_pool_id is not None: body['instance_pool_id'] = self.instance_pool_id + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'InstancePoolPermissionsRequest': + return cls(access_control_list=_repeated(d, 'access_control_list', InstancePoolAccessControlRequest), + instance_pool_id=d.get('instance_pool_id', None)) + + class InstancePoolState(Enum): """Current state of the instance pool.""" @@ -3326,6 +3813,43 @@ def get(self, policy_id: str, **kwargs) -> Policy: json = self._api.do('GET', '/api/2.0/policies/clusters/get', query=query) return Policy.from_dict(json) + def get_cluster_policy_permission_levels(self, cluster_policy_id: str, + **kwargs) -> GetClusterPolicyPermissionLevelsResponse: + """Get cluster policy permission levels. + + Gets the permission levels that a user can have on an object. + + :param cluster_policy_id: str + The cluster policy for which to get or manage permissions. + + :returns: :class:`GetClusterPolicyPermissionLevelsResponse` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetClusterPolicyPermissionLevelsRequest(cluster_policy_id=cluster_policy_id) + + json = self._api.do( + 'GET', f'/api/2.0/permissions/cluster-policies/{request.cluster_policy_id}/permissionLevels') + return GetClusterPolicyPermissionLevelsResponse.from_dict(json) + + def get_cluster_policy_permissions(self, cluster_policy_id: str, **kwargs) -> ClusterPolicyPermissions: + """Get cluster policy permissions. + + Gets the permissions of a cluster policy. Cluster policies can inherit permissions from their root + object. + + :param cluster_policy_id: str + The cluster policy for which to get or manage permissions. + + :returns: :class:`ClusterPolicyPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetClusterPolicyPermissionsRequest(cluster_policy_id=cluster_policy_id) + + json = self._api.do('GET', f'/api/2.0/permissions/cluster-policies/{request.cluster_policy_id}') + return ClusterPolicyPermissions.from_dict(json) + def list(self, *, sort_column: Optional[ListSortColumn] = None, @@ -3355,6 +3879,61 @@ def list(self, json = self._api.do('GET', '/api/2.0/policies/clusters/list', query=query) return [Policy.from_dict(v) for v in json.get('policies', [])] + def set_cluster_policy_permissions(self, + cluster_policy_id: str, + *, + access_control_list: Optional[ + List[ClusterPolicyAccessControlRequest]] = None, + **kwargs) -> ClusterPolicyPermissions: + """Set cluster policy permissions. + + Sets permissions on a cluster policy. Cluster policies can inherit permissions from their root object. + + :param cluster_policy_id: str + The cluster policy for which to get or manage permissions. + :param access_control_list: List[:class:`ClusterPolicyAccessControlRequest`] (optional) + + :returns: :class:`ClusterPolicyPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = ClusterPolicyPermissionsRequest(access_control_list=access_control_list, + cluster_policy_id=cluster_policy_id) + body = request.as_dict() + + json = self._api.do('PUT', + f'/api/2.0/permissions/cluster-policies/{request.cluster_policy_id}', + body=body) + return ClusterPolicyPermissions.from_dict(json) + + def update_cluster_policy_permissions(self, + cluster_policy_id: str, + *, + access_control_list: Optional[ + List[ClusterPolicyAccessControlRequest]] = None, + **kwargs) -> ClusterPolicyPermissions: + """Update cluster policy permissions. + + Updates the permissions on a cluster policy. Cluster policies can inherit permissions from their root + object. + + :param cluster_policy_id: str + The cluster policy for which to get or manage permissions. + :param access_control_list: List[:class:`ClusterPolicyAccessControlRequest`] (optional) + + :returns: :class:`ClusterPolicyPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = ClusterPolicyPermissionsRequest(access_control_list=access_control_list, + cluster_policy_id=cluster_policy_id) + body = request.as_dict() + + json = self._api.do('PATCH', + f'/api/2.0/permissions/cluster-policies/{request.cluster_policy_id}', + body=body) + return ClusterPolicyPermissions.from_dict(json) + class ClustersAPI: """The Clusters API allows you to create, start, edit, list, terminate, and delete clusters. @@ -4045,6 +4624,40 @@ def get(self, cluster_id: str, **kwargs) -> ClusterDetails: json = self._api.do('GET', '/api/2.0/clusters/get', query=query) return ClusterDetails.from_dict(json) + def get_cluster_permission_levels(self, cluster_id: str, **kwargs) -> GetClusterPermissionLevelsResponse: + """Get cluster permission levels. + + Gets the permission levels that a user can have on an object. + + :param cluster_id: str + The cluster for which to get or manage permissions. + + :returns: :class:`GetClusterPermissionLevelsResponse` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetClusterPermissionLevelsRequest(cluster_id=cluster_id) + + json = self._api.do('GET', f'/api/2.0/permissions/clusters/{request.cluster_id}/permissionLevels') + return GetClusterPermissionLevelsResponse.from_dict(json) + + def get_cluster_permissions(self, cluster_id: str, **kwargs) -> ClusterPermissions: + """Get cluster permissions. + + Gets the permissions of a cluster. Clusters can inherit permissions from their root object. + + :param cluster_id: str + The cluster for which to get or manage permissions. + + :returns: :class:`ClusterPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetClusterPermissionsRequest(cluster_id=cluster_id) + + json = self._api.do('GET', f'/api/2.0/permissions/clusters/{request.cluster_id}') + return ClusterPermissions.from_dict(json) + def list(self, *, can_use_client: Optional[str] = None, **kwargs) -> Iterator[ClusterDetails]: """List all clusters. @@ -4213,6 +4826,30 @@ def restart_and_wait(self, timeout=timedelta(minutes=20)) -> ClusterDetails: return self.restart(cluster_id=cluster_id, restart_user=restart_user).result(timeout=timeout) + def set_cluster_permissions(self, + cluster_id: str, + *, + access_control_list: Optional[List[ClusterAccessControlRequest]] = None, + **kwargs) -> ClusterPermissions: + """Set cluster permissions. + + Sets permissions on a cluster. Clusters can inherit permissions from their root object. + + :param cluster_id: str + The cluster for which to get or manage permissions. + :param access_control_list: List[:class:`ClusterAccessControlRequest`] (optional) + + :returns: :class:`ClusterPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = ClusterPermissionsRequest(access_control_list=access_control_list, + cluster_id=cluster_id) + body = request.as_dict() + + json = self._api.do('PUT', f'/api/2.0/permissions/clusters/{request.cluster_id}', body=body) + return ClusterPermissions.from_dict(json) + def spark_versions(self) -> GetSparkVersionsResponse: """List available Spark versions. @@ -4269,6 +4906,30 @@ def unpin(self, cluster_id: str, **kwargs): body = request.as_dict() self._api.do('POST', '/api/2.0/clusters/unpin', body=body) + def update_cluster_permissions(self, + cluster_id: str, + *, + access_control_list: Optional[List[ClusterAccessControlRequest]] = None, + **kwargs) -> ClusterPermissions: + """Update cluster permissions. + + Updates the permissions on a cluster. Clusters can inherit permissions from their root object. + + :param cluster_id: str + The cluster for which to get or manage permissions. + :param access_control_list: List[:class:`ClusterAccessControlRequest`] (optional) + + :returns: :class:`ClusterPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = ClusterPermissionsRequest(access_control_list=access_control_list, + cluster_id=cluster_id) + body = request.as_dict() + + json = self._api.do('PATCH', f'/api/2.0/permissions/clusters/{request.cluster_id}', body=body) + return ClusterPermissions.from_dict(json) + class CommandExecutionAPI: """This API allows execution of Python, Scala, SQL, or R commands on running Databricks Clusters.""" @@ -4958,6 +5619,43 @@ def get(self, instance_pool_id: str, **kwargs) -> GetInstancePool: json = self._api.do('GET', '/api/2.0/instance-pools/get', query=query) return GetInstancePool.from_dict(json) + def get_instance_pool_permission_levels(self, instance_pool_id: str, + **kwargs) -> GetInstancePoolPermissionLevelsResponse: + """Get instance pool permission levels. + + Gets the permission levels that a user can have on an object. + + :param instance_pool_id: str + The instance pool for which to get or manage permissions. + + :returns: :class:`GetInstancePoolPermissionLevelsResponse` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetInstancePoolPermissionLevelsRequest(instance_pool_id=instance_pool_id) + + json = self._api.do( + 'GET', f'/api/2.0/permissions/instance-pools/{request.instance_pool_id}/permissionLevels') + return GetInstancePoolPermissionLevelsResponse.from_dict(json) + + def get_instance_pool_permissions(self, instance_pool_id: str, **kwargs) -> InstancePoolPermissions: + """Get instance pool permissions. + + Gets the permissions of an instance pool. Instance pools can inherit permissions from their root + object. + + :param instance_pool_id: str + The instance pool for which to get or manage permissions. + + :returns: :class:`InstancePoolPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetInstancePoolPermissionsRequest(instance_pool_id=instance_pool_id) + + json = self._api.do('GET', f'/api/2.0/permissions/instance-pools/{request.instance_pool_id}') + return InstancePoolPermissions.from_dict(json) + def list(self) -> Iterator[InstancePoolAndStats]: """List instance pool info. @@ -4969,6 +5667,61 @@ def list(self) -> Iterator[InstancePoolAndStats]: json = self._api.do('GET', '/api/2.0/instance-pools/list') return [InstancePoolAndStats.from_dict(v) for v in json.get('instance_pools', [])] + def set_instance_pool_permissions(self, + instance_pool_id: str, + *, + access_control_list: Optional[ + List[InstancePoolAccessControlRequest]] = None, + **kwargs) -> InstancePoolPermissions: + """Set instance pool permissions. + + Sets permissions on an instance pool. Instance pools can inherit permissions from their root object. + + :param instance_pool_id: str + The instance pool for which to get or manage permissions. + :param access_control_list: List[:class:`InstancePoolAccessControlRequest`] (optional) + + :returns: :class:`InstancePoolPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = InstancePoolPermissionsRequest(access_control_list=access_control_list, + instance_pool_id=instance_pool_id) + body = request.as_dict() + + json = self._api.do('PUT', + f'/api/2.0/permissions/instance-pools/{request.instance_pool_id}', + body=body) + return InstancePoolPermissions.from_dict(json) + + def update_instance_pool_permissions(self, + instance_pool_id: str, + *, + access_control_list: Optional[ + List[InstancePoolAccessControlRequest]] = None, + **kwargs) -> InstancePoolPermissions: + """Update instance pool permissions. + + Updates the permissions on an instance pool. Instance pools can inherit permissions from their root + object. + + :param instance_pool_id: str + The instance pool for which to get or manage permissions. + :param access_control_list: List[:class:`InstancePoolAccessControlRequest`] (optional) + + :returns: :class:`InstancePoolPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = InstancePoolPermissionsRequest(access_control_list=access_control_list, + instance_pool_id=instance_pool_id) + body = request.as_dict() + + json = self._api.do('PATCH', + f'/api/2.0/permissions/instance-pools/{request.instance_pool_id}', + body=body) + return InstancePoolPermissions.from_dict(json) + class InstanceProfilesAPI: """The Instance Profiles API allows admins to add, list, and remove instance profiles that users can launch diff --git a/databricks/sdk/service/iam.py b/databricks/sdk/service/iam.py index 13dfad36..7ed0ebcb 100755 --- a/databricks/sdk/service/iam.py +++ b/databricks/sdk/service/iam.py @@ -39,6 +39,7 @@ def from_dict(cls, d: Dict[str, any]) -> 'AccessControlRequest': @dataclass class AccessControlResponse: all_permissions: Optional['List[Permission]'] = None + display_name: Optional[str] = None group_name: Optional[str] = None service_principal_name: Optional[str] = None user_name: Optional[str] = None @@ -46,6 +47,7 @@ class AccessControlResponse: def as_dict(self) -> dict: 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 @@ -55,6 +57,7 @@ def as_dict(self) -> dict: @classmethod def from_dict(cls, d: Dict[str, any]) -> 'AccessControlResponse': return cls(all_permissions=_repeated(d, 'all_permissions', Permission), + 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)) @@ -163,16 +166,16 @@ class GetAssignableRolesForResourceRequest: @dataclass class GetAssignableRolesForResourceResponse: - roles: Optional['List[str]'] = None + roles: Optional['List[Role]'] = None def as_dict(self) -> dict: body = {} - if self.roles: body['roles'] = [v for v in self.roles] + if self.roles: body['roles'] = [v.as_dict() for v in self.roles] return body @classmethod def from_dict(cls, d: Dict[str, any]) -> 'GetAssignableRolesForResourceResponse': - return cls(roles=d.get('roles', None)) + return cls(roles=_repeated(d, 'roles', Role)) @dataclass @@ -182,9 +185,23 @@ class GetGroupRequest: id: str +@dataclass +class GetPasswordPermissionLevelsResponse: + permission_levels: Optional['List[PasswordPermissionsDescription]'] = None + + def as_dict(self) -> dict: + body = {} + if self.permission_levels: body['permission_levels'] = [v.as_dict() for v in self.permission_levels] + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'GetPasswordPermissionLevelsResponse': + return cls(permission_levels=_repeated(d, 'permission_levels', PasswordPermissionsDescription)) + + @dataclass class GetPermissionLevelsRequest: - """Get permission levels""" + """Get object permission levels""" request_object_type: str request_object_id: str @@ -509,6 +526,136 @@ def from_dict(cls, d: Dict[str, any]) -> 'PartialUpdate': schema=d.get('schema', None)) +@dataclass +class PasswordAccessControlRequest: + group_name: Optional[str] = None + permission_level: Optional['PasswordPermissionLevel'] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'PasswordAccessControlRequest': + return cls(group_name=d.get('group_name', None), + permission_level=_enum(d, 'permission_level', PasswordPermissionLevel), + service_principal_name=d.get('service_principal_name', None), + user_name=d.get('user_name', None)) + + +@dataclass +class PasswordAccessControlResponse: + all_permissions: Optional['List[PasswordPermission]'] = None + display_name: Optional[str] = None + group_name: Optional[str] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'PasswordAccessControlResponse': + return cls(all_permissions=_repeated(d, 'all_permissions', PasswordPermission), + 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 PasswordPermission: + inherited: Optional[bool] = None + inherited_from_object: Optional['List[str]'] = None + permission_level: Optional['PasswordPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'PasswordPermission': + return cls(inherited=d.get('inherited', None), + inherited_from_object=d.get('inherited_from_object', None), + permission_level=_enum(d, 'permission_level', PasswordPermissionLevel)) + + +class PasswordPermissionLevel(Enum): + """Permission level""" + + CAN_USE = 'CAN_USE' + + +@dataclass +class PasswordPermissions: + access_control_list: Optional['List[PasswordAccessControlResponse]'] = None + object_id: Optional[str] = None + object_type: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'PasswordPermissions': + return cls(access_control_list=_repeated(d, 'access_control_list', PasswordAccessControlResponse), + object_id=d.get('object_id', None), + object_type=d.get('object_type', None)) + + +@dataclass +class PasswordPermissionsDescription: + description: Optional[str] = None + permission_level: Optional['PasswordPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'PasswordPermissionsDescription': + return cls(description=d.get('description', None), + permission_level=_enum(d, 'permission_level', PasswordPermissionLevel)) + + +@dataclass +class PasswordPermissionsRequest: + access_control_list: Optional['List[PasswordAccessControlRequest]'] = None + + def as_dict(self) -> dict: + body = {} + if self.access_control_list: + body['access_control_list'] = [v.as_dict() for v in self.access_control_list] + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'PasswordPermissionsRequest': + return cls(access_control_list=_repeated(d, 'access_control_list', PasswordAccessControlRequest)) + + @dataclass class Patch: op: Optional['PatchOp'] = None @@ -711,6 +858,20 @@ def from_dict(cls, d: Dict[str, any]) -> 'ResourceMeta': return cls(resource_type=d.get('resourceType', None)) +@dataclass +class Role: + name: str + + def as_dict(self) -> dict: + body = {} + if self.name is not None: body['name'] = self.name + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'Role': + return cls(name=d.get('name', None)) + + @dataclass class RuleSetResponse: etag: Optional[str] = None @@ -1964,7 +2125,49 @@ def update(self, class PermissionsAPI: """Permissions API are used to create read, write, edit, update and manage access for various users on - different objects and endpoints.""" + different objects and endpoints. + + * **[Cluster permissions](:service:clusters)** — Manage which users can manage, restart, or attach to + clusters. + + * **[Cluster policy permissions](:service:clusterpolicies)** — Manage which users can use cluster + policies. + + * **[Delta Live Tables pipeline permissions](:service:pipelines)** — Manage which users can view, + manage, run, cancel, or own a Delta Live Tables pipeline. + + * **[Job permissions](:service:jobs)** — Manage which users can view, manage, trigger, cancel, or own a + job. + + * **[MLflow experiment permissions](:service:experiments)** — Manage which users can read, edit, or + manage MLflow experiments. + + * **[MLflow registered model permissions](:service:modelregistry)** — Manage which users can read, edit, + or manage MLflow registered models. + + * **[Password permissions](:service:users)** — Manage which users can use password login when SSO is + enabled. + + * **[Instance Pool permissions](:service:instancepools)** — Manage which users can manage or attach to + pools. + + * **[Repo permissions](repos)** — Manage which users can read, run, edit, or manage a repo. + + * **[Serving endpoint permissions](:service:servingendpoints)** — Manage which users can view, query, or + manage a serving endpoint. + + * **[SQL warehouse permissions](:service:warehouses)** — Manage which users can use or manage SQL + warehouses. + + * **[Token permissions](:service:tokenmanagement)** — Manage which users can create or use tokens. + + * **[Workspace object permissions](:service:workspace)** — Manage which users can read, run, edit, or + manage directories, files, and notebooks. + + For the mapping of the required permissions for specific actions or abilities and other important + information, see [Access Control]. + + [Access Control]: https://docs.databricks.com/security/auth-authz/access-control/index.html""" def __init__(self, api_client): self._api = api_client @@ -1972,8 +2175,8 @@ def __init__(self, api_client): def get(self, request_object_type: str, request_object_id: str, **kwargs) -> ObjectPermissions: """Get object permissions. - Gets the permission of an object. Objects can inherit permissions from their parent objects or root - objects. + Gets the permissions of an object. Objects can inherit permissions from their parent objects or root + object. :param request_object_type: str @@ -1992,7 +2195,7 @@ def get(self, request_object_type: str, request_object_id: str, **kwargs) -> Obj def get_permission_levels(self, request_object_type: str, request_object_id: str, **kwargs) -> GetPermissionLevelsResponse: - """Get permission levels. + """Get object permission levels. Gets the permission levels that a user can have on an object. @@ -2019,18 +2222,18 @@ def set(self, request_object_id: str, *, access_control_list: Optional[List[AccessControlRequest]] = None, - **kwargs): - """Set permissions. + **kwargs) -> ObjectPermissions: + """Set object permissions. - Sets permissions on object. Objects can inherit permissions from their parent objects and root - objects. + Sets permissions on an object. Objects can inherit permissions from their parent objects or root + object. :param request_object_type: str :param request_object_id: str :param access_control_list: List[:class:`AccessControlRequest`] (optional) - + :returns: :class:`ObjectPermissions` """ request = kwargs.get('request', None) if not request: # request is not given through keyed args @@ -2038,26 +2241,29 @@ def set(self, request_object_id=request_object_id, request_object_type=request_object_type) body = request.as_dict() - self._api.do('PUT', - f'/api/2.0/permissions/{request.request_object_type}/{request.request_object_id}', - body=body) + + json = self._api.do('PUT', + f'/api/2.0/permissions/{request.request_object_type}/{request.request_object_id}', + body=body) + return ObjectPermissions.from_dict(json) def update(self, request_object_type: str, request_object_id: str, *, access_control_list: Optional[List[AccessControlRequest]] = None, - **kwargs): - """Update permission. + **kwargs) -> ObjectPermissions: + """Update object permissions. - Updates the permissions on an object. + Updates the permissions on an object. Objects can inherit permissions from their parent objects or + root object. :param request_object_type: str :param request_object_id: str :param access_control_list: List[:class:`AccessControlRequest`] (optional) - + :returns: :class:`ObjectPermissions` """ request = kwargs.get('request', None) if not request: # request is not given through keyed args @@ -2065,9 +2271,11 @@ def update(self, request_object_id=request_object_id, request_object_type=request_object_type) body = request.as_dict() - self._api.do('PATCH', - f'/api/2.0/permissions/{request.request_object_type}/{request.request_object_id}', - body=body) + + json = self._api.do('PATCH', + f'/api/2.0/permissions/{request.request_object_type}/{request.request_object_id}', + body=body) + return ObjectPermissions.from_dict(json) class ServicePrincipalsAPI: @@ -2387,6 +2595,28 @@ def get(self, id: str, **kwargs) -> User: json = self._api.do('GET', f'/api/2.0/preview/scim/v2/Users/{request.id}') return User.from_dict(json) + def get_password_permission_levels(self) -> GetPasswordPermissionLevelsResponse: + """Get password permission levels. + + Gets the permission levels that a user can have on an object. + + :returns: :class:`GetPasswordPermissionLevelsResponse` + """ + + json = self._api.do('GET', '/api/2.0/permissions/authorization/passwords/permissionLevels') + return GetPasswordPermissionLevelsResponse.from_dict(json) + + def get_password_permissions(self) -> PasswordPermissions: + """Get password permissions. + + Gets the permissions of all passwords. Passwords can inherit permissions from their root object. + + :returns: :class:`PasswordPermissions` + """ + + json = self._api.do('GET', '/api/2.0/permissions/authorization/passwords') + return PasswordPermissions.from_dict(json) + def list(self, *, attributes: Optional[str] = None, @@ -2470,6 +2700,26 @@ def patch(self, body = request.as_dict() self._api.do('PATCH', f'/api/2.0/preview/scim/v2/Users/{request.id}', body=body) + def set_password_permissions(self, + *, + access_control_list: Optional[List[PasswordAccessControlRequest]] = None, + **kwargs) -> PasswordPermissions: + """Set password permissions. + + Sets permissions on all passwords. Passwords can inherit permissions from their root object. + + :param access_control_list: List[:class:`PasswordAccessControlRequest`] (optional) + + :returns: :class:`PasswordPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = PasswordPermissionsRequest(access_control_list=access_control_list) + body = request.as_dict() + + json = self._api.do('PUT', '/api/2.0/permissions/authorization/passwords', body=body) + return PasswordPermissions.from_dict(json) + def update(self, id: str, *, @@ -2520,6 +2770,26 @@ def update(self, body = request.as_dict() self._api.do('PUT', f'/api/2.0/preview/scim/v2/Users/{request.id}', body=body) + def update_password_permissions(self, + *, + access_control_list: Optional[List[PasswordAccessControlRequest]] = None, + **kwargs) -> PasswordPermissions: + """Update password permissions. + + Updates the permissions on all passwords. Passwords can inherit permissions from their root object. + + :param access_control_list: List[:class:`PasswordAccessControlRequest`] (optional) + + :returns: :class:`PasswordPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = PasswordPermissionsRequest(access_control_list=access_control_list) + body = request.as_dict() + + json = self._api.do('PATCH', '/api/2.0/permissions/authorization/passwords', body=body) + return PasswordPermissions.from_dict(json) + class WorkspaceAssignmentAPI: """The Workspace Permission Assignment API allows you to manage workspace permissions for principals in your diff --git a/databricks/sdk/service/jobs.py b/databricks/sdk/service/jobs.py index deaff968..c334af4f 100755 --- a/databricks/sdk/service/jobs.py +++ b/databricks/sdk/service/jobs.py @@ -477,6 +477,34 @@ class Format(Enum): SINGLE_TASK = 'SINGLE_TASK' +@dataclass +class GetJobPermissionLevelsRequest: + """Get job permission levels""" + + job_id: str + + +@dataclass +class GetJobPermissionLevelsResponse: + permission_levels: Optional['List[JobPermissionsDescription]'] = None + + def as_dict(self) -> dict: + body = {} + if self.permission_levels: body['permission_levels'] = [v.as_dict() for v in self.permission_levels] + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'GetJobPermissionLevelsResponse': + return cls(permission_levels=_repeated(d, 'permission_levels', JobPermissionsDescription)) + + +@dataclass +class GetJobPermissionsRequest: + """Get job permissions""" + + job_id: str + + @dataclass class GetJobRequest: """Get a single job""" @@ -592,6 +620,57 @@ def from_dict(cls, d: Dict[str, any]) -> 'Job': trigger_history=_from_dict(d, 'trigger_history', TriggerHistory)) +@dataclass +class JobAccessControlRequest: + group_name: Optional[str] = None + permission_level: Optional['JobPermissionLevel'] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'JobAccessControlRequest': + return cls(group_name=d.get('group_name', None), + permission_level=_enum(d, 'permission_level', JobPermissionLevel), + service_principal_name=d.get('service_principal_name', None), + user_name=d.get('user_name', None)) + + +@dataclass +class JobAccessControlResponse: + all_permissions: Optional['List[JobPermission]'] = None + display_name: Optional[str] = None + group_name: Optional[str] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'JobAccessControlResponse': + return cls(all_permissions=_repeated(d, 'all_permissions', JobPermission), + 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 JobCluster: job_cluster_key: str @@ -709,6 +788,91 @@ def from_dict(cls, d: Dict[str, any]) -> 'JobParameterDefinition': return cls(default=d.get('default', None), name=d.get('name', None)) +@dataclass +class JobPermission: + inherited: Optional[bool] = None + inherited_from_object: Optional['List[str]'] = None + permission_level: Optional['JobPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'JobPermission': + return cls(inherited=d.get('inherited', None), + inherited_from_object=d.get('inherited_from_object', None), + permission_level=_enum(d, 'permission_level', JobPermissionLevel)) + + +class JobPermissionLevel(Enum): + """Permission level""" + + CAN_MANAGE = 'CAN_MANAGE' + CAN_MANAGE_RUN = 'CAN_MANAGE_RUN' + CAN_VIEW = 'CAN_VIEW' + IS_OWNER = 'IS_OWNER' + + +@dataclass +class JobPermissions: + access_control_list: Optional['List[JobAccessControlResponse]'] = None + object_id: Optional[str] = None + object_type: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'JobPermissions': + return cls(access_control_list=_repeated(d, 'access_control_list', JobAccessControlResponse), + object_id=d.get('object_id', None), + object_type=d.get('object_type', None)) + + +@dataclass +class JobPermissionsDescription: + description: Optional[str] = None + permission_level: Optional['JobPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'JobPermissionsDescription': + return cls(description=d.get('description', None), + permission_level=_enum(d, 'permission_level', JobPermissionLevel)) + + +@dataclass +class JobPermissionsRequest: + access_control_list: Optional['List[JobAccessControlRequest]'] = None + job_id: Optional[str] = None + + def as_dict(self) -> dict: + body = {} + if self.access_control_list: + body['access_control_list'] = [v.as_dict() for v in self.access_control_list] + if self.job_id is not None: body['job_id'] = self.job_id + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'JobPermissionsRequest': + return cls(access_control_list=_repeated(d, 'access_control_list', JobAccessControlRequest), + job_id=d.get('job_id', None)) + + @dataclass class JobRunAs: """Write-only setting, available only in Create/Update/Reset and Submit calls. Specifies the user @@ -2881,6 +3045,40 @@ def get(self, job_id: int, **kwargs) -> Job: json = self._api.do('GET', '/api/2.1/jobs/get', query=query) return Job.from_dict(json) + def get_job_permission_levels(self, job_id: str, **kwargs) -> GetJobPermissionLevelsResponse: + """Get job permission levels. + + Gets the permission levels that a user can have on an object. + + :param job_id: str + The job for which to get or manage permissions. + + :returns: :class:`GetJobPermissionLevelsResponse` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetJobPermissionLevelsRequest(job_id=job_id) + + json = self._api.do('GET', f'/api/2.0/permissions/jobs/{request.job_id}/permissionLevels') + return GetJobPermissionLevelsResponse.from_dict(json) + + def get_job_permissions(self, job_id: str, **kwargs) -> JobPermissions: + """Get job permissions. + + Gets the permissions of a job. Jobs can inherit permissions from their root object. + + :param job_id: str + The job for which to get or manage permissions. + + :returns: :class:`JobPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetJobPermissionsRequest(job_id=job_id) + + json = self._api.do('GET', f'/api/2.0/permissions/jobs/{request.job_id}') + return JobPermissions.from_dict(json) + def get_run(self, run_id: int, *, include_history: Optional[bool] = None, **kwargs) -> Run: """Get a single job run. @@ -3398,6 +3596,29 @@ def run_now_and_wait(self, spark_submit_params=spark_submit_params, sql_params=sql_params).result(timeout=timeout) + def set_job_permissions(self, + job_id: str, + *, + access_control_list: Optional[List[JobAccessControlRequest]] = None, + **kwargs) -> JobPermissions: + """Set job permissions. + + Sets permissions on a job. Jobs can inherit permissions from their root object. + + :param job_id: str + The job for which to get or manage permissions. + :param access_control_list: List[:class:`JobAccessControlRequest`] (optional) + + :returns: :class:`JobPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = JobPermissionsRequest(access_control_list=access_control_list, job_id=job_id) + body = request.as_dict() + + json = self._api.do('PUT', f'/api/2.0/permissions/jobs/{request.job_id}', body=body) + return JobPermissions.from_dict(json) + def submit(self, *, access_control_list: Optional[List[iam.AccessControlRequest]] = None, @@ -3534,3 +3755,26 @@ def update(self, request = UpdateJob(fields_to_remove=fields_to_remove, job_id=job_id, new_settings=new_settings) body = request.as_dict() self._api.do('POST', '/api/2.1/jobs/update', body=body) + + def update_job_permissions(self, + job_id: str, + *, + access_control_list: Optional[List[JobAccessControlRequest]] = None, + **kwargs) -> JobPermissions: + """Update job permissions. + + Updates the permissions on a job. Jobs can inherit permissions from their root object. + + :param job_id: str + The job for which to get or manage permissions. + :param access_control_list: List[:class:`JobAccessControlRequest`] (optional) + + :returns: :class:`JobPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = JobPermissionsRequest(access_control_list=access_control_list, job_id=job_id) + body = request.as_dict() + + json = self._api.do('PATCH', f'/api/2.0/permissions/jobs/{request.job_id}', body=body) + return JobPermissions.from_dict(json) diff --git a/databricks/sdk/service/ml.py b/databricks/sdk/service/ml.py index 7962fea2..95aa0f0c 100755 --- a/databricks/sdk/service/ml.py +++ b/databricks/sdk/service/ml.py @@ -599,6 +599,141 @@ def from_dict(cls, d: Dict[str, any]) -> 'Experiment': tags=_repeated(d, 'tags', ExperimentTag)) +@dataclass +class ExperimentAccessControlRequest: + group_name: Optional[str] = None + permission_level: Optional['ExperimentPermissionLevel'] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ExperimentAccessControlRequest': + return cls(group_name=d.get('group_name', None), + permission_level=_enum(d, 'permission_level', ExperimentPermissionLevel), + service_principal_name=d.get('service_principal_name', None), + user_name=d.get('user_name', None)) + + +@dataclass +class ExperimentAccessControlResponse: + all_permissions: Optional['List[ExperimentPermission]'] = None + display_name: Optional[str] = None + group_name: Optional[str] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ExperimentAccessControlResponse': + return cls(all_permissions=_repeated(d, 'all_permissions', ExperimentPermission), + 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 ExperimentPermission: + inherited: Optional[bool] = None + inherited_from_object: Optional['List[str]'] = None + permission_level: Optional['ExperimentPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ExperimentPermission': + return cls(inherited=d.get('inherited', None), + inherited_from_object=d.get('inherited_from_object', None), + permission_level=_enum(d, 'permission_level', ExperimentPermissionLevel)) + + +class ExperimentPermissionLevel(Enum): + """Permission level""" + + CAN_EDIT = 'CAN_EDIT' + CAN_MANAGE = 'CAN_MANAGE' + CAN_READ = 'CAN_READ' + + +@dataclass +class ExperimentPermissions: + access_control_list: Optional['List[ExperimentAccessControlResponse]'] = None + object_id: Optional[str] = None + object_type: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ExperimentPermissions': + return cls(access_control_list=_repeated(d, 'access_control_list', ExperimentAccessControlResponse), + object_id=d.get('object_id', None), + object_type=d.get('object_type', None)) + + +@dataclass +class ExperimentPermissionsDescription: + description: Optional[str] = None + permission_level: Optional['ExperimentPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ExperimentPermissionsDescription': + return cls(description=d.get('description', None), + permission_level=_enum(d, 'permission_level', ExperimentPermissionLevel)) + + +@dataclass +class ExperimentPermissionsRequest: + access_control_list: Optional['List[ExperimentAccessControlRequest]'] = None + experiment_id: Optional[str] = None + + def as_dict(self) -> dict: + body = {} + if self.access_control_list: + body['access_control_list'] = [v.as_dict() for v in self.access_control_list] + if self.experiment_id is not None: body['experiment_id'] = self.experiment_id + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ExperimentPermissionsRequest': + return cls(access_control_list=_repeated(d, 'access_control_list', ExperimentAccessControlRequest), + experiment_id=d.get('experiment_id', None)) + + @dataclass class ExperimentTag: key: Optional[str] = None @@ -654,6 +789,34 @@ def from_dict(cls, d: Dict[str, any]) -> 'GetExperimentByNameResponse': return cls(experiment=_from_dict(d, 'experiment', Experiment)) +@dataclass +class GetExperimentPermissionLevelsRequest: + """Get experiment permission levels""" + + experiment_id: str + + +@dataclass +class GetExperimentPermissionLevelsResponse: + permission_levels: Optional['List[ExperimentPermissionsDescription]'] = None + + def as_dict(self) -> dict: + body = {} + if self.permission_levels: body['permission_levels'] = [v.as_dict() for v in self.permission_levels] + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'GetExperimentPermissionLevelsResponse': + return cls(permission_levels=_repeated(d, 'permission_levels', ExperimentPermissionsDescription)) + + +@dataclass +class GetExperimentPermissionsRequest: + """Get experiment permissions""" + + experiment_id: str + + @dataclass class GetExperimentRequest: """Get an experiment""" @@ -784,6 +947,34 @@ def from_dict(cls, d: Dict[str, any]) -> 'GetModelVersionResponse': return cls(model_version=_from_dict(d, 'model_version', ModelVersion)) +@dataclass +class GetRegisteredModelPermissionLevelsRequest: + """Get registered model permission levels""" + + registered_model_id: str + + +@dataclass +class GetRegisteredModelPermissionLevelsResponse: + permission_levels: Optional['List[RegisteredModelPermissionsDescription]'] = None + + def as_dict(self) -> dict: + body = {} + if self.permission_levels: body['permission_levels'] = [v.as_dict() for v in self.permission_levels] + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'GetRegisteredModelPermissionLevelsResponse': + return cls(permission_levels=_repeated(d, 'permission_levels', RegisteredModelPermissionsDescription)) + + +@dataclass +class GetRegisteredModelPermissionsRequest: + """Get registered model permissions""" + + registered_model_id: str + + @dataclass class GetRunRequest: """Get a run""" @@ -1402,6 +1593,145 @@ class PermissionLevel(Enum): CAN_READ = 'CAN_READ' +@dataclass +class RegisteredModelAccessControlRequest: + group_name: Optional[str] = None + permission_level: Optional['RegisteredModelPermissionLevel'] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'RegisteredModelAccessControlRequest': + return cls(group_name=d.get('group_name', None), + permission_level=_enum(d, 'permission_level', RegisteredModelPermissionLevel), + service_principal_name=d.get('service_principal_name', None), + user_name=d.get('user_name', None)) + + +@dataclass +class RegisteredModelAccessControlResponse: + all_permissions: Optional['List[RegisteredModelPermission]'] = None + display_name: Optional[str] = None + group_name: Optional[str] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'RegisteredModelAccessControlResponse': + return cls(all_permissions=_repeated(d, 'all_permissions', RegisteredModelPermission), + 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 RegisteredModelPermission: + inherited: Optional[bool] = None + inherited_from_object: Optional['List[str]'] = None + permission_level: Optional['RegisteredModelPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'RegisteredModelPermission': + return cls(inherited=d.get('inherited', None), + inherited_from_object=d.get('inherited_from_object', None), + permission_level=_enum(d, 'permission_level', RegisteredModelPermissionLevel)) + + +class RegisteredModelPermissionLevel(Enum): + """Permission level""" + + CAN_EDIT = 'CAN_EDIT' + CAN_MANAGE = 'CAN_MANAGE' + CAN_MANAGE_PRODUCTION_VERSIONS = 'CAN_MANAGE_PRODUCTION_VERSIONS' + CAN_MANAGE_STAGING_VERSIONS = 'CAN_MANAGE_STAGING_VERSIONS' + CAN_READ = 'CAN_READ' + + +@dataclass +class RegisteredModelPermissions: + access_control_list: Optional['List[RegisteredModelAccessControlResponse]'] = None + object_id: Optional[str] = None + object_type: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'RegisteredModelPermissions': + return cls(access_control_list=_repeated(d, 'access_control_list', + RegisteredModelAccessControlResponse), + object_id=d.get('object_id', None), + object_type=d.get('object_type', None)) + + +@dataclass +class RegisteredModelPermissionsDescription: + description: Optional[str] = None + permission_level: Optional['RegisteredModelPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'RegisteredModelPermissionsDescription': + return cls(description=d.get('description', None), + permission_level=_enum(d, 'permission_level', RegisteredModelPermissionLevel)) + + +@dataclass +class RegisteredModelPermissionsRequest: + access_control_list: Optional['List[RegisteredModelAccessControlRequest]'] = None + registered_model_id: Optional[str] = None + + def as_dict(self) -> dict: + body = {} + if self.access_control_list: + body['access_control_list'] = [v.as_dict() for v in self.access_control_list] + if self.registered_model_id is not None: body['registered_model_id'] = self.registered_model_id + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'RegisteredModelPermissionsRequest': + return cls(access_control_list=_repeated(d, 'access_control_list', + RegisteredModelAccessControlRequest), + registered_model_id=d.get('registered_model_id', None)) + + @dataclass class RegistryWebhook: creation_timestamp: Optional[int] = None @@ -2393,6 +2723,42 @@ def get_experiment(self, experiment_id: str, **kwargs) -> Experiment: json = self._api.do('GET', '/api/2.0/mlflow/experiments/get', query=query) return Experiment.from_dict(json) + def get_experiment_permission_levels(self, experiment_id: str, + **kwargs) -> GetExperimentPermissionLevelsResponse: + """Get experiment permission levels. + + Gets the permission levels that a user can have on an object. + + :param experiment_id: str + The experiment for which to get or manage permissions. + + :returns: :class:`GetExperimentPermissionLevelsResponse` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetExperimentPermissionLevelsRequest(experiment_id=experiment_id) + + json = self._api.do('GET', + f'/api/2.0/permissions/experiments/{request.experiment_id}/permissionLevels') + return GetExperimentPermissionLevelsResponse.from_dict(json) + + def get_experiment_permissions(self, experiment_id: str, **kwargs) -> ExperimentPermissions: + """Get experiment permissions. + + Gets the permissions of an experiment. Experiments can inherit permissions from their root object. + + :param experiment_id: str + The experiment for which to get or manage permissions. + + :returns: :class:`ExperimentPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetExperimentPermissionsRequest(experiment_id=experiment_id) + + json = self._api.do('GET', f'/api/2.0/permissions/experiments/{request.experiment_id}') + return ExperimentPermissions.from_dict(json) + def get_history(self, metric_key: str, *, @@ -2873,6 +3239,30 @@ def search_runs(self, return body['page_token'] = json['next_page_token'] + def set_experiment_permissions(self, + experiment_id: str, + *, + access_control_list: Optional[List[ExperimentAccessControlRequest]] = None, + **kwargs) -> ExperimentPermissions: + """Set experiment permissions. + + Sets permissions on an experiment. Experiments can inherit permissions from their root object. + + :param experiment_id: str + The experiment for which to get or manage permissions. + :param access_control_list: List[:class:`ExperimentAccessControlRequest`] (optional) + + :returns: :class:`ExperimentPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = ExperimentPermissionsRequest(access_control_list=access_control_list, + experiment_id=experiment_id) + body = request.as_dict() + + json = self._api.do('PUT', f'/api/2.0/permissions/experiments/{request.experiment_id}', body=body) + return ExperimentPermissions.from_dict(json) + def set_experiment_tag(self, experiment_id: str, key: str, value: str, **kwargs): """Set a tag. @@ -2944,6 +3334,31 @@ def update_experiment(self, experiment_id: str, *, new_name: Optional[str] = Non body = request.as_dict() self._api.do('POST', '/api/2.0/mlflow/experiments/update', body=body) + def update_experiment_permissions(self, + experiment_id: str, + *, + access_control_list: Optional[ + List[ExperimentAccessControlRequest]] = None, + **kwargs) -> ExperimentPermissions: + """Update experiment permissions. + + Updates the permissions on an experiment. Experiments can inherit permissions from their root object. + + :param experiment_id: str + The experiment for which to get or manage permissions. + :param access_control_list: List[:class:`ExperimentAccessControlRequest`] (optional) + + :returns: :class:`ExperimentPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = ExperimentPermissionsRequest(access_control_list=access_control_list, + experiment_id=experiment_id) + body = request.as_dict() + + json = self._api.do('PATCH', f'/api/2.0/permissions/experiments/{request.experiment_id}', body=body) + return ExperimentPermissions.from_dict(json) + def update_run(self, *, end_time: Optional[int] = None, @@ -3504,6 +3919,44 @@ def get_model_version_download_uri(self, name: str, version: str, json = self._api.do('GET', '/api/2.0/mlflow/model-versions/get-download-uri', query=query) return GetModelVersionDownloadUriResponse.from_dict(json) + def get_registered_model_permission_levels(self, registered_model_id: str, + **kwargs) -> GetRegisteredModelPermissionLevelsResponse: + """Get registered model permission levels. + + Gets the permission levels that a user can have on an object. + + :param registered_model_id: str + The registered model for which to get or manage permissions. + + :returns: :class:`GetRegisteredModelPermissionLevelsResponse` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetRegisteredModelPermissionLevelsRequest(registered_model_id=registered_model_id) + + json = self._api.do( + 'GET', f'/api/2.0/permissions/registered-models/{request.registered_model_id}/permissionLevels') + return GetRegisteredModelPermissionLevelsResponse.from_dict(json) + + def get_registered_model_permissions(self, registered_model_id: str, + **kwargs) -> RegisteredModelPermissions: + """Get registered model permissions. + + Gets the permissions of a registered model. Registered models can inherit permissions from their root + object. + + :param registered_model_id: str + The registered model for which to get or manage permissions. + + :returns: :class:`RegisteredModelPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetRegisteredModelPermissionsRequest(registered_model_id=registered_model_id) + + json = self._api.do('GET', f'/api/2.0/permissions/registered-models/{request.registered_model_id}') + return RegisteredModelPermissions.from_dict(json) + def list_models(self, *, max_results: Optional[int] = None, @@ -3806,6 +4259,34 @@ def set_model_version_tag(self, name: str, version: str, key: str, value: str, * body = request.as_dict() self._api.do('POST', '/api/2.0/mlflow/model-versions/set-tag', body=body) + def set_registered_model_permissions(self, + registered_model_id: str, + *, + access_control_list: Optional[ + List[RegisteredModelAccessControlRequest]] = None, + **kwargs) -> RegisteredModelPermissions: + """Set registered model permissions. + + Sets permissions on a registered model. Registered models can inherit permissions from their root + object. + + :param registered_model_id: str + The registered model for which to get or manage permissions. + :param access_control_list: List[:class:`RegisteredModelAccessControlRequest`] (optional) + + :returns: :class:`RegisteredModelPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = RegisteredModelPermissionsRequest(access_control_list=access_control_list, + registered_model_id=registered_model_id) + body = request.as_dict() + + json = self._api.do('PUT', + f'/api/2.0/permissions/registered-models/{request.registered_model_id}', + body=body) + return RegisteredModelPermissions.from_dict(json) + def test_registry_webhook(self, id: str, *, @@ -3940,6 +4421,34 @@ def update_model_version(self, name: str, version: str, *, description: Optional body = request.as_dict() self._api.do('PATCH', '/api/2.0/mlflow/model-versions/update', body=body) + def update_registered_model_permissions(self, + registered_model_id: str, + *, + access_control_list: Optional[ + List[RegisteredModelAccessControlRequest]] = None, + **kwargs) -> RegisteredModelPermissions: + """Update registered model permissions. + + Updates the permissions on a registered model. Registered models can inherit permissions from their + root object. + + :param registered_model_id: str + The registered model for which to get or manage permissions. + :param access_control_list: List[:class:`RegisteredModelAccessControlRequest`] (optional) + + :returns: :class:`RegisteredModelPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = RegisteredModelPermissionsRequest(access_control_list=access_control_list, + registered_model_id=registered_model_id) + body = request.as_dict() + + json = self._api.do('PATCH', + f'/api/2.0/permissions/registered-models/{request.registered_model_id}', + body=body) + return RegisteredModelPermissions.from_dict(json) + def update_webhook(self, id: str, *, diff --git a/databricks/sdk/service/oauth2.py b/databricks/sdk/service/oauth2.py index 458b24eb..1bc39c47 100755 --- a/databricks/sdk/service/oauth2.py +++ b/databricks/sdk/service/oauth2.py @@ -16,6 +16,7 @@ class CreateCustomAppIntegration: name: str redirect_urls: 'List[str]' confidential: Optional[bool] = None + scopes: Optional['List[str]'] = None token_access_policy: Optional['TokenAccessPolicy'] = None def as_dict(self) -> dict: @@ -23,6 +24,7 @@ def as_dict(self) -> dict: if self.confidential is not None: body['confidential'] = self.confidential if self.name is not None: body['name'] = self.name if self.redirect_urls: body['redirect_urls'] = [v for v in self.redirect_urls] + if self.scopes: body['scopes'] = [v for v in self.scopes] if self.token_access_policy: body['token_access_policy'] = self.token_access_policy.as_dict() return body @@ -31,6 +33,7 @@ def from_dict(cls, d: Dict[str, any]) -> 'CreateCustomAppIntegration': return cls(confidential=d.get('confidential', None), name=d.get('name', None), redirect_urls=d.get('redirect_urls', None), + scopes=d.get('scopes', None), token_access_policy=_from_dict(d, 'token_access_policy', TokenAccessPolicy)) @@ -384,6 +387,7 @@ def create(self, redirect_urls: List[str], *, confidential: Optional[bool] = None, + scopes: Optional[List[str]] = None, token_access_policy: Optional[TokenAccessPolicy] = None, **kwargs) -> CreateCustomAppIntegrationOutput: """Create Custom OAuth App Integration. @@ -398,6 +402,9 @@ def create(self, List of oauth redirect urls :param confidential: bool (optional) indicates if an oauth client-secret should be generated + :param scopes: List[str] (optional) + OAuth scopes granted to the application. Supported scopes: all-apis, sql, offline_access, openid, + profile, email. :param token_access_policy: :class:`TokenAccessPolicy` (optional) Token access policy @@ -408,6 +415,7 @@ def create(self, request = CreateCustomAppIntegration(confidential=confidential, name=name, redirect_urls=redirect_urls, + scopes=scopes, token_access_policy=token_access_policy) body = request.as_dict() diff --git a/databricks/sdk/service/pipelines.py b/databricks/sdk/service/pipelines.py index 465ec36b..906edbc5 100755 --- a/databricks/sdk/service/pipelines.py +++ b/databricks/sdk/service/pipelines.py @@ -264,6 +264,34 @@ def from_dict(cls, d: Dict[str, any]) -> 'Filters': return cls(exclude=d.get('exclude', None), include=d.get('include', None)) +@dataclass +class GetPipelinePermissionLevelsRequest: + """Get pipeline permission levels""" + + pipeline_id: str + + +@dataclass +class GetPipelinePermissionLevelsResponse: + permission_levels: Optional['List[PipelinePermissionsDescription]'] = None + + def as_dict(self) -> dict: + body = {} + if self.permission_levels: body['permission_levels'] = [v.as_dict() for v in self.permission_levels] + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'GetPipelinePermissionLevelsResponse': + return cls(permission_levels=_repeated(d, 'permission_levels', PipelinePermissionsDescription)) + + +@dataclass +class GetPipelinePermissionsRequest: + """Get pipeline permissions""" + + pipeline_id: str + + @dataclass class GetPipelineRequest: """Get a pipeline""" @@ -516,6 +544,57 @@ def from_dict(cls, d: Dict[str, any]) -> 'Origin': update_id=d.get('update_id', None)) +@dataclass +class PipelineAccessControlRequest: + group_name: Optional[str] = None + permission_level: Optional['PipelinePermissionLevel'] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'PipelineAccessControlRequest': + return cls(group_name=d.get('group_name', None), + permission_level=_enum(d, 'permission_level', PipelinePermissionLevel), + service_principal_name=d.get('service_principal_name', None), + user_name=d.get('user_name', None)) + + +@dataclass +class PipelineAccessControlResponse: + all_permissions: Optional['List[PipelinePermission]'] = None + display_name: Optional[str] = None + group_name: Optional[str] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'PipelineAccessControlResponse': + return cls(all_permissions=_repeated(d, 'all_permissions', PipelinePermission), + 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 PipelineCluster: apply_policy_default_values: Optional[bool] = None @@ -641,6 +720,91 @@ def from_dict(cls, d: Dict[str, any]) -> 'PipelineLibrary': notebook=_from_dict(d, 'notebook', NotebookLibrary)) +@dataclass +class PipelinePermission: + inherited: Optional[bool] = None + inherited_from_object: Optional['List[str]'] = None + permission_level: Optional['PipelinePermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'PipelinePermission': + return cls(inherited=d.get('inherited', None), + inherited_from_object=d.get('inherited_from_object', None), + permission_level=_enum(d, 'permission_level', PipelinePermissionLevel)) + + +class PipelinePermissionLevel(Enum): + """Permission level""" + + CAN_MANAGE = 'CAN_MANAGE' + CAN_RUN = 'CAN_RUN' + CAN_VIEW = 'CAN_VIEW' + IS_OWNER = 'IS_OWNER' + + +@dataclass +class PipelinePermissions: + access_control_list: Optional['List[PipelineAccessControlResponse]'] = None + object_id: Optional[str] = None + object_type: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'PipelinePermissions': + return cls(access_control_list=_repeated(d, 'access_control_list', PipelineAccessControlResponse), + object_id=d.get('object_id', None), + object_type=d.get('object_type', None)) + + +@dataclass +class PipelinePermissionsDescription: + description: Optional[str] = None + permission_level: Optional['PipelinePermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'PipelinePermissionsDescription': + return cls(description=d.get('description', None), + permission_level=_enum(d, 'permission_level', PipelinePermissionLevel)) + + +@dataclass +class PipelinePermissionsRequest: + access_control_list: Optional['List[PipelineAccessControlRequest]'] = None + pipeline_id: Optional[str] = None + + def as_dict(self) -> dict: + body = {} + if self.access_control_list: + body['access_control_list'] = [v.as_dict() for v in self.access_control_list] + if self.pipeline_id is not None: body['pipeline_id'] = self.pipeline_id + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'PipelinePermissionsRequest': + return cls(access_control_list=_repeated(d, 'access_control_list', PipelineAccessControlRequest), + pipeline_id=d.get('pipeline_id', None)) + + @dataclass class PipelineSpec: catalog: Optional[str] = None @@ -1189,6 +1353,41 @@ def get(self, pipeline_id: str, **kwargs) -> GetPipelineResponse: json = self._api.do('GET', f'/api/2.0/pipelines/{request.pipeline_id}') return GetPipelineResponse.from_dict(json) + def get_pipeline_permission_levels(self, pipeline_id: str, + **kwargs) -> GetPipelinePermissionLevelsResponse: + """Get pipeline permission levels. + + Gets the permission levels that a user can have on an object. + + :param pipeline_id: str + The pipeline for which to get or manage permissions. + + :returns: :class:`GetPipelinePermissionLevelsResponse` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetPipelinePermissionLevelsRequest(pipeline_id=pipeline_id) + + json = self._api.do('GET', f'/api/2.0/permissions/pipelines/{request.pipeline_id}/permissionLevels') + return GetPipelinePermissionLevelsResponse.from_dict(json) + + def get_pipeline_permissions(self, pipeline_id: str, **kwargs) -> PipelinePermissions: + """Get pipeline permissions. + + Gets the permissions of a pipeline. Pipelines can inherit permissions from their root object. + + :param pipeline_id: str + The pipeline for which to get or manage permissions. + + :returns: :class:`PipelinePermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetPipelinePermissionsRequest(pipeline_id=pipeline_id) + + json = self._api.do('GET', f'/api/2.0/permissions/pipelines/{request.pipeline_id}') + return PipelinePermissions.from_dict(json) + def get_update(self, pipeline_id: str, update_id: str, **kwargs) -> GetUpdateResponse: """Get a pipeline update. @@ -1379,6 +1578,30 @@ def reset(self, pipeline_id: str, **kwargs) -> Wait[GetPipelineResponse]: def reset_and_wait(self, pipeline_id: str, timeout=timedelta(minutes=20)) -> GetPipelineResponse: return self.reset(pipeline_id=pipeline_id).result(timeout=timeout) + def set_pipeline_permissions(self, + pipeline_id: str, + *, + access_control_list: Optional[List[PipelineAccessControlRequest]] = None, + **kwargs) -> PipelinePermissions: + """Set pipeline permissions. + + Sets permissions on a pipeline. Pipelines can inherit permissions from their root object. + + :param pipeline_id: str + The pipeline for which to get or manage permissions. + :param access_control_list: List[:class:`PipelineAccessControlRequest`] (optional) + + :returns: :class:`PipelinePermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = PipelinePermissionsRequest(access_control_list=access_control_list, + pipeline_id=pipeline_id) + body = request.as_dict() + + json = self._api.do('PUT', f'/api/2.0/permissions/pipelines/{request.pipeline_id}', body=body) + return PipelinePermissions.from_dict(json) + def start_update(self, pipeline_id: str, *, @@ -1533,3 +1756,27 @@ def update(self, trigger=trigger) body = request.as_dict() self._api.do('PUT', f'/api/2.0/pipelines/{request.pipeline_id}', body=body) + + def update_pipeline_permissions(self, + pipeline_id: str, + *, + access_control_list: Optional[List[PipelineAccessControlRequest]] = None, + **kwargs) -> PipelinePermissions: + """Update pipeline permissions. + + Updates the permissions on a pipeline. Pipelines can inherit permissions from their root object. + + :param pipeline_id: str + The pipeline for which to get or manage permissions. + :param access_control_list: List[:class:`PipelineAccessControlRequest`] (optional) + + :returns: :class:`PipelinePermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = PipelinePermissionsRequest(access_control_list=access_control_list, + pipeline_id=pipeline_id) + body = request.as_dict() + + json = self._api.do('PATCH', f'/api/2.0/permissions/pipelines/{request.pipeline_id}', body=body) + return PipelinePermissions.from_dict(json) diff --git a/databricks/sdk/service/provisioning.py b/databricks/sdk/service/provisioning.py index 5c2b9584..225ccb95 100755 --- a/databricks/sdk/service/provisioning.py +++ b/databricks/sdk/service/provisioning.py @@ -248,6 +248,8 @@ class CreateWorkspaceRequest: cloud_resource_container: Optional['CloudResourceContainer'] = None credentials_id: Optional[str] = None deployment_name: Optional[str] = None + gcp_managed_network_config: Optional['GcpManagedNetworkConfig'] = None + gke_config: Optional['GkeConfig'] = None location: Optional[str] = None managed_services_customer_managed_key_id: Optional[str] = None network_id: Optional[str] = None @@ -264,6 +266,9 @@ def as_dict(self) -> dict: body['cloud_resource_container'] = self.cloud_resource_container.as_dict() if self.credentials_id is not None: body['credentials_id'] = self.credentials_id if self.deployment_name is not None: body['deployment_name'] = self.deployment_name + if self.gcp_managed_network_config: + body['gcp_managed_network_config'] = self.gcp_managed_network_config.as_dict() + if self.gke_config: body['gke_config'] = self.gke_config.as_dict() if self.location is not None: body['location'] = self.location if self.managed_services_customer_managed_key_id is not None: body['managed_services_customer_managed_key_id'] = self.managed_services_customer_managed_key_id @@ -285,6 +290,9 @@ def from_dict(cls, d: Dict[str, any]) -> 'CreateWorkspaceRequest': cloud_resource_container=_from_dict(d, 'cloud_resource_container', CloudResourceContainer), credentials_id=d.get('credentials_id', None), deployment_name=d.get('deployment_name', None), + gcp_managed_network_config=_from_dict(d, 'gcp_managed_network_config', + GcpManagedNetworkConfig), + gke_config=_from_dict(d, 'gke_config', GkeConfig), location=d.get('location', None), managed_services_customer_managed_key_id=d.get('managed_services_customer_managed_key_id', None), @@ -1877,6 +1885,8 @@ def create(self, cloud_resource_container: Optional[CloudResourceContainer] = None, credentials_id: Optional[str] = None, deployment_name: Optional[str] = None, + gcp_managed_network_config: Optional[GcpManagedNetworkConfig] = None, + gke_config: Optional[GkeConfig] = None, location: Optional[str] = None, managed_services_customer_managed_key_id: Optional[str] = None, network_id: Optional[str] = None, @@ -1933,6 +1943,27 @@ def create(self, If a new workspace omits this property, the server generates a unique deployment name for you with the pattern `dbc-xxxxxxxx-xxxx`. + :param gcp_managed_network_config: :class:`GcpManagedNetworkConfig` (optional) + The network settings for the workspace. The configurations are only for Databricks-managed VPCs. It + is ignored if you specify a customer-managed VPC in the `network_id` field.", All the IP range + configurations must be mutually exclusive. An attempt to create a workspace fails if Databricks + detects an IP range overlap. + + Specify custom IP ranges in CIDR format. The IP ranges for these fields must not overlap, and all IP + addresses must be entirely within the following ranges: `10.0.0.0/8`, `100.64.0.0/10`, + `172.16.0.0/12`, `192.168.0.0/16`, and `240.0.0.0/4`. + + The sizes of these IP ranges affect the maximum number of nodes for the workspace. + + **Important**: Confirm the IP ranges used by your Databricks workspace before creating the + workspace. You cannot change them after your workspace is deployed. If the IP address ranges for + your Databricks are too small, IP exhaustion can occur, causing your Databricks jobs to fail. To + determine the address range sizes that you need, Databricks provides a calculator as a Microsoft + Excel spreadsheet. See [calculate subnet sizes for a new workspace]. + + [calculate subnet sizes for a new workspace]: https://docs.gcp.databricks.com/administration-guide/cloud-configurations/gcp/network-sizing.html + :param gke_config: :class:`GkeConfig` (optional) + The configurations for the GKE cluster of a Databricks workspace. :param location: str (optional) The Google Cloud region of the workspace data plane in your Google account. For example, `us-east4`. :param managed_services_customer_managed_key_id: str (optional) @@ -1972,6 +2003,8 @@ def create(self, cloud_resource_container=cloud_resource_container, credentials_id=credentials_id, deployment_name=deployment_name, + gcp_managed_network_config=gcp_managed_network_config, + gke_config=gke_config, location=location, managed_services_customer_managed_key_id=managed_services_customer_managed_key_id, network_id=network_id, @@ -1995,6 +2028,8 @@ def create_and_wait( cloud_resource_container: Optional[CloudResourceContainer] = None, credentials_id: Optional[str] = None, deployment_name: Optional[str] = None, + gcp_managed_network_config: Optional[GcpManagedNetworkConfig] = None, + gke_config: Optional[GkeConfig] = None, location: Optional[str] = None, managed_services_customer_managed_key_id: Optional[str] = None, network_id: Optional[str] = None, @@ -2008,6 +2043,8 @@ def create_and_wait( cloud_resource_container=cloud_resource_container, credentials_id=credentials_id, deployment_name=deployment_name, + gcp_managed_network_config=gcp_managed_network_config, + gke_config=gke_config, location=location, managed_services_customer_managed_key_id=managed_services_customer_managed_key_id, network_id=network_id, diff --git a/databricks/sdk/service/serving.py b/databricks/sdk/service/serving.py index 690e66c4..5d74a88e 100755 --- a/databricks/sdk/service/serving.py +++ b/databricks/sdk/service/serving.py @@ -183,6 +183,34 @@ class ExportMetricsRequest: name: str +@dataclass +class GetServingEndpointPermissionLevelsRequest: + """Get serving endpoint permission levels""" + + serving_endpoint_id: str + + +@dataclass +class GetServingEndpointPermissionLevelsResponse: + permission_levels: Optional['List[ServingEndpointPermissionsDescription]'] = None + + def as_dict(self) -> dict: + body = {} + if self.permission_levels: body['permission_levels'] = [v.as_dict() for v in self.permission_levels] + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'GetServingEndpointPermissionLevelsResponse': + return cls(permission_levels=_repeated(d, 'permission_levels', ServingEndpointPermissionsDescription)) + + +@dataclass +class GetServingEndpointPermissionsRequest: + """Get serving endpoint permissions""" + + serving_endpoint_id: str + + @dataclass class GetServingEndpointRequest: """Get a single serving endpoint""" @@ -257,11 +285,13 @@ class ServedModelInput: workload_size: str scale_to_zero_enabled: bool environment_vars: Optional['Dict[str,str]'] = None + instance_profile_arn: Optional[str] = None name: Optional[str] = None def as_dict(self) -> dict: body = {} if self.environment_vars: body['environment_vars'] = self.environment_vars + if self.instance_profile_arn is not None: body['instance_profile_arn'] = self.instance_profile_arn if self.model_name is not None: body['model_name'] = self.model_name if self.model_version is not None: body['model_version'] = self.model_version if self.name is not None: body['name'] = self.name @@ -272,6 +302,7 @@ def as_dict(self) -> dict: @classmethod def from_dict(cls, d: Dict[str, any]) -> 'ServedModelInput': return cls(environment_vars=d.get('environment_vars', None), + instance_profile_arn=d.get('instance_profile_arn', None), model_name=d.get('model_name', None), model_version=d.get('model_version', None), name=d.get('name', None), @@ -284,6 +315,7 @@ class ServedModelOutput: creation_timestamp: Optional[int] = None creator: Optional[str] = None environment_vars: Optional['Dict[str,str]'] = None + instance_profile_arn: Optional[str] = None model_name: Optional[str] = None model_version: Optional[str] = None name: Optional[str] = None @@ -296,6 +328,7 @@ def as_dict(self) -> dict: if self.creation_timestamp is not None: body['creation_timestamp'] = self.creation_timestamp if self.creator is not None: body['creator'] = self.creator if self.environment_vars: body['environment_vars'] = self.environment_vars + if self.instance_profile_arn is not None: body['instance_profile_arn'] = self.instance_profile_arn if self.model_name is not None: body['model_name'] = self.model_name if self.model_version is not None: body['model_version'] = self.model_version if self.name is not None: body['name'] = self.name @@ -309,6 +342,7 @@ def from_dict(cls, d: Dict[str, any]) -> 'ServedModelOutput': return cls(creation_timestamp=d.get('creation_timestamp', None), creator=d.get('creator', None), environment_vars=d.get('environment_vars', None), + instance_profile_arn=d.get('instance_profile_arn', None), model_name=d.get('model_name', None), model_version=d.get('model_version', None), name=d.get('name', None), @@ -420,6 +454,57 @@ def from_dict(cls, d: Dict[str, any]) -> 'ServingEndpoint': state=_from_dict(d, 'state', EndpointState)) +@dataclass +class ServingEndpointAccessControlRequest: + group_name: Optional[str] = None + permission_level: Optional['ServingEndpointPermissionLevel'] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ServingEndpointAccessControlRequest': + return cls(group_name=d.get('group_name', None), + permission_level=_enum(d, 'permission_level', ServingEndpointPermissionLevel), + service_principal_name=d.get('service_principal_name', None), + user_name=d.get('user_name', None)) + + +@dataclass +class ServingEndpointAccessControlResponse: + all_permissions: Optional['List[ServingEndpointPermission]'] = None + display_name: Optional[str] = None + group_name: Optional[str] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ServingEndpointAccessControlResponse': + return cls(all_permissions=_repeated(d, 'all_permissions', ServingEndpointPermission), + 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 ServingEndpointDetailed: config: Optional['EndpointCoreConfigOutput'] = None @@ -467,6 +552,92 @@ class ServingEndpointDetailedPermissionLevel(Enum): CAN_VIEW = 'CAN_VIEW' +@dataclass +class ServingEndpointPermission: + inherited: Optional[bool] = None + inherited_from_object: Optional['List[str]'] = None + permission_level: Optional['ServingEndpointPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ServingEndpointPermission': + return cls(inherited=d.get('inherited', None), + inherited_from_object=d.get('inherited_from_object', None), + permission_level=_enum(d, 'permission_level', ServingEndpointPermissionLevel)) + + +class ServingEndpointPermissionLevel(Enum): + """Permission level""" + + CAN_MANAGE = 'CAN_MANAGE' + CAN_QUERY = 'CAN_QUERY' + CAN_VIEW = 'CAN_VIEW' + + +@dataclass +class ServingEndpointPermissions: + access_control_list: Optional['List[ServingEndpointAccessControlResponse]'] = None + object_id: Optional[str] = None + object_type: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ServingEndpointPermissions': + return cls(access_control_list=_repeated(d, 'access_control_list', + ServingEndpointAccessControlResponse), + object_id=d.get('object_id', None), + object_type=d.get('object_type', None)) + + +@dataclass +class ServingEndpointPermissionsDescription: + description: Optional[str] = None + permission_level: Optional['ServingEndpointPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ServingEndpointPermissionsDescription': + return cls(description=d.get('description', None), + permission_level=_enum(d, 'permission_level', ServingEndpointPermissionLevel)) + + +@dataclass +class ServingEndpointPermissionsRequest: + access_control_list: Optional['List[ServingEndpointAccessControlRequest]'] = None + serving_endpoint_id: Optional[str] = None + + def as_dict(self) -> dict: + body = {} + if self.access_control_list: + body['access_control_list'] = [v.as_dict() for v in self.access_control_list] + if self.serving_endpoint_id is not None: body['serving_endpoint_id'] = self.serving_endpoint_id + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'ServingEndpointPermissionsRequest': + return cls(access_control_list=_repeated(d, 'access_control_list', + ServingEndpointAccessControlRequest), + serving_endpoint_id=d.get('serving_endpoint_id', None)) + + @dataclass class TrafficConfig: routes: Optional['List[Route]'] = None @@ -623,6 +794,44 @@ def get(self, name: str, **kwargs) -> ServingEndpointDetailed: json = self._api.do('GET', f'/api/2.0/serving-endpoints/{request.name}') return ServingEndpointDetailed.from_dict(json) + def get_serving_endpoint_permission_levels(self, serving_endpoint_id: str, + **kwargs) -> GetServingEndpointPermissionLevelsResponse: + """Get serving endpoint permission levels. + + Gets the permission levels that a user can have on an object. + + :param serving_endpoint_id: str + The serving endpoint for which to get or manage permissions. + + :returns: :class:`GetServingEndpointPermissionLevelsResponse` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetServingEndpointPermissionLevelsRequest(serving_endpoint_id=serving_endpoint_id) + + json = self._api.do( + 'GET', f'/api/2.0/permissions/serving-endpoints/{request.serving_endpoint_id}/permissionLevels') + return GetServingEndpointPermissionLevelsResponse.from_dict(json) + + def get_serving_endpoint_permissions(self, serving_endpoint_id: str, + **kwargs) -> ServingEndpointPermissions: + """Get serving endpoint permissions. + + Gets the permissions of a serving endpoint. Serving endpoints can inherit permissions from their root + object. + + :param serving_endpoint_id: str + The serving endpoint for which to get or manage permissions. + + :returns: :class:`ServingEndpointPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetServingEndpointPermissionsRequest(serving_endpoint_id=serving_endpoint_id) + + json = self._api.do('GET', f'/api/2.0/permissions/serving-endpoints/{request.serving_endpoint_id}') + return ServingEndpointPermissions.from_dict(json) + def list(self) -> Iterator[ServingEndpoint]: """Retrieve all serving endpoints. @@ -668,6 +877,34 @@ def query(self, name: str, **kwargs) -> QueryEndpointResponse: json = self._api.do('POST', f'/serving-endpoints/{request.name}/invocations') return QueryEndpointResponse.from_dict(json) + def set_serving_endpoint_permissions(self, + serving_endpoint_id: str, + *, + access_control_list: Optional[ + List[ServingEndpointAccessControlRequest]] = None, + **kwargs) -> ServingEndpointPermissions: + """Set serving endpoint permissions. + + Sets permissions on a serving endpoint. Serving endpoints can inherit permissions from their root + object. + + :param serving_endpoint_id: str + The serving endpoint for which to get or manage permissions. + :param access_control_list: List[:class:`ServingEndpointAccessControlRequest`] (optional) + + :returns: :class:`ServingEndpointPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = ServingEndpointPermissionsRequest(access_control_list=access_control_list, + serving_endpoint_id=serving_endpoint_id) + body = request.as_dict() + + json = self._api.do('PUT', + f'/api/2.0/permissions/serving-endpoints/{request.serving_endpoint_id}', + body=body) + return ServingEndpointPermissions.from_dict(json) + def update_config(self, served_models: List[ServedModelInput], name: str, @@ -712,3 +949,31 @@ def update_config_and_wait( timeout=timedelta(minutes=20)) -> ServingEndpointDetailed: return self.update_config(name=name, served_models=served_models, traffic_config=traffic_config).result(timeout=timeout) + + def update_serving_endpoint_permissions(self, + serving_endpoint_id: str, + *, + access_control_list: Optional[ + List[ServingEndpointAccessControlRequest]] = None, + **kwargs) -> ServingEndpointPermissions: + """Update serving endpoint permissions. + + Updates the permissions on a serving endpoint. Serving endpoints can inherit permissions from their + root object. + + :param serving_endpoint_id: str + The serving endpoint for which to get or manage permissions. + :param access_control_list: List[:class:`ServingEndpointAccessControlRequest`] (optional) + + :returns: :class:`ServingEndpointPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = ServingEndpointPermissionsRequest(access_control_list=access_control_list, + serving_endpoint_id=serving_endpoint_id) + body = request.as_dict() + + json = self._api.do('PATCH', + f'/api/2.0/permissions/serving-endpoints/{request.serving_endpoint_id}', + body=body) + return ServingEndpointPermissions.from_dict(json) diff --git a/databricks/sdk/service/settings.py b/databricks/sdk/service/settings.py index ca144902..a8468eb1 100755 --- a/databricks/sdk/service/settings.py +++ b/databricks/sdk/service/settings.py @@ -263,6 +263,20 @@ class GetTokenManagementRequest: token_id: str +@dataclass +class GetTokenPermissionLevelsResponse: + permission_levels: Optional['List[TokenPermissionsDescription]'] = None + + def as_dict(self) -> dict: + body = {} + if self.permission_levels: body['permission_levels'] = [v.as_dict() for v in self.permission_levels] + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'GetTokenPermissionLevelsResponse': + return cls(permission_levels=_repeated(d, 'permission_levels', TokenPermissionsDescription)) + + @dataclass class IpAccessListInfo: address_count: Optional[int] = None @@ -458,6 +472,57 @@ def from_dict(cls, d: Dict[str, any]) -> 'RevokeTokenRequest': return cls(token_id=d.get('token_id', None)) +@dataclass +class TokenAccessControlRequest: + group_name: Optional[str] = None + permission_level: Optional['TokenPermissionLevel'] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'TokenAccessControlRequest': + return cls(group_name=d.get('group_name', None), + permission_level=_enum(d, 'permission_level', TokenPermissionLevel), + service_principal_name=d.get('service_principal_name', None), + user_name=d.get('user_name', None)) + + +@dataclass +class TokenAccessControlResponse: + all_permissions: Optional['List[TokenPermission]'] = None + display_name: Optional[str] = None + group_name: Optional[str] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'TokenAccessControlResponse': + return cls(all_permissions=_repeated(d, 'all_permissions', TokenPermission), + 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 TokenInfo: comment: Optional[str] = None @@ -490,6 +555,85 @@ def from_dict(cls, d: Dict[str, any]) -> 'TokenInfo': token_id=d.get('token_id', None)) +@dataclass +class TokenPermission: + inherited: Optional[bool] = None + inherited_from_object: Optional['List[str]'] = None + permission_level: Optional['TokenPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'TokenPermission': + return cls(inherited=d.get('inherited', None), + inherited_from_object=d.get('inherited_from_object', None), + permission_level=_enum(d, 'permission_level', TokenPermissionLevel)) + + +class TokenPermissionLevel(Enum): + """Permission level""" + + CAN_USE = 'CAN_USE' + + +@dataclass +class TokenPermissions: + access_control_list: Optional['List[TokenAccessControlResponse]'] = None + object_id: Optional[str] = None + object_type: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'TokenPermissions': + return cls(access_control_list=_repeated(d, 'access_control_list', TokenAccessControlResponse), + object_id=d.get('object_id', None), + object_type=d.get('object_type', None)) + + +@dataclass +class TokenPermissionsDescription: + description: Optional[str] = None + permission_level: Optional['TokenPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'TokenPermissionsDescription': + return cls(description=d.get('description', None), + permission_level=_enum(d, 'permission_level', TokenPermissionLevel)) + + +@dataclass +class TokenPermissionsRequest: + access_control_list: Optional['List[TokenAccessControlRequest]'] = None + + def as_dict(self) -> dict: + body = {} + if self.access_control_list: + body['access_control_list'] = [v.as_dict() for v in self.access_control_list] + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'TokenPermissionsRequest': + return cls(access_control_list=_repeated(d, 'access_control_list', TokenAccessControlRequest)) + + @dataclass class UpdateAccountNetworkPolicyRequest: """Update Account Network Policy""" @@ -1230,6 +1374,28 @@ def get(self, token_id: str, **kwargs) -> TokenInfo: json = self._api.do('GET', f'/api/2.0/token-management/tokens/{request.token_id}') return TokenInfo.from_dict(json) + def get_token_permission_levels(self) -> GetTokenPermissionLevelsResponse: + """Get token permission levels. + + Gets the permission levels that a user can have on an object. + + :returns: :class:`GetTokenPermissionLevelsResponse` + """ + + json = self._api.do('GET', '/api/2.0/permissions/authorization/tokens/permissionLevels') + return GetTokenPermissionLevelsResponse.from_dict(json) + + def get_token_permissions(self) -> TokenPermissions: + """Get token permissions. + + Gets the permissions of all tokens. Tokens can inherit permissions from their root object. + + :returns: :class:`TokenPermissions` + """ + + json = self._api.do('GET', '/api/2.0/permissions/authorization/tokens') + return TokenPermissions.from_dict(json) + def list(self, *, created_by_id: Optional[str] = None, @@ -1258,6 +1424,46 @@ def list(self, json = self._api.do('GET', '/api/2.0/token-management/tokens', query=query) return [TokenInfo.from_dict(v) for v in json.get('token_infos', [])] + def set_token_permissions(self, + *, + access_control_list: Optional[List[TokenAccessControlRequest]] = None, + **kwargs) -> TokenPermissions: + """Set token permissions. + + Sets permissions on all tokens. Tokens can inherit permissions from their root object. + + :param access_control_list: List[:class:`TokenAccessControlRequest`] (optional) + + :returns: :class:`TokenPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = TokenPermissionsRequest(access_control_list=access_control_list) + body = request.as_dict() + + json = self._api.do('PUT', '/api/2.0/permissions/authorization/tokens', body=body) + return TokenPermissions.from_dict(json) + + def update_token_permissions(self, + *, + access_control_list: Optional[List[TokenAccessControlRequest]] = None, + **kwargs) -> TokenPermissions: + """Update token permissions. + + Updates the permissions on all tokens. Tokens can inherit permissions from their root object. + + :param access_control_list: List[:class:`TokenAccessControlRequest`] (optional) + + :returns: :class:`TokenPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = TokenPermissionsRequest(access_control_list=access_control_list) + body = request.as_dict() + + json = self._api.do('PATCH', '/api/2.0/permissions/authorization/tokens', body=body) + return TokenPermissions.from_dict(json) + class TokensAPI: """The Token API allows you to create, list, and revoke tokens that can be used to authenticate and access diff --git a/databricks/sdk/service/sql.py b/databricks/sdk/service/sql.py index 836e2431..cdbaa55c 100755 --- a/databricks/sdk/service/sql.py +++ b/databricks/sdk/service/sql.py @@ -212,7 +212,6 @@ def from_dict(cls, d: Dict[str, any]) -> 'ChannelInfo': class ChannelName(Enum): - """Name of the channel""" CHANNEL_NAME_CURRENT = 'CHANNEL_NAME_CURRENT' CHANNEL_NAME_CUSTOM = 'CHANNEL_NAME_CUSTOM' @@ -1079,6 +1078,34 @@ class GetStatementResultChunkNRequest: chunk_index: int +@dataclass +class GetWarehousePermissionLevelsRequest: + """Get SQL warehouse permission levels""" + + warehouse_id: str + + +@dataclass +class GetWarehousePermissionLevelsResponse: + permission_levels: Optional['List[WarehousePermissionsDescription]'] = None + + def as_dict(self) -> dict: + body = {} + if self.permission_levels: body['permission_levels'] = [v.as_dict() for v in self.permission_levels] + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'GetWarehousePermissionLevelsResponse': + return cls(permission_levels=_repeated(d, 'permission_levels', WarehousePermissionsDescription)) + + +@dataclass +class GetWarehousePermissionsRequest: + """Get SQL warehouse permissions""" + + warehouse_id: str + + @dataclass class GetWarehouseRequest: """Get warehouse info""" @@ -1555,6 +1582,7 @@ def from_dict(cls, d: Dict[str, any]) -> 'QueryFilter': @dataclass class QueryInfo: + can_subscribe_to_live_query: Optional[bool] = None channel_used: Optional['ChannelInfo'] = None duration: Optional[int] = None endpoint_id: Optional[str] = None @@ -1580,6 +1608,8 @@ class QueryInfo: def as_dict(self) -> dict: body = {} + if self.can_subscribe_to_live_query is not None: + body['canSubscribeToLiveQuery'] = self.can_subscribe_to_live_query if self.channel_used: body['channel_used'] = self.channel_used.as_dict() if self.duration is not None: body['duration'] = self.duration if self.endpoint_id is not None: body['endpoint_id'] = self.endpoint_id @@ -1606,7 +1636,8 @@ def as_dict(self) -> dict: @classmethod def from_dict(cls, d: Dict[str, any]) -> 'QueryInfo': - return cls(channel_used=_from_dict(d, 'channel_used', ChannelInfo), + return cls(can_subscribe_to_live_query=d.get('canSubscribeToLiveQuery', None), + channel_used=_from_dict(d, 'channel_used', ChannelInfo), duration=d.get('duration', None), endpoint_id=d.get('endpoint_id', None), error_message=d.get('error_message', None), @@ -1659,10 +1690,17 @@ class QueryMetrics: compilation_time_ms: Optional[int] = None execution_time_ms: Optional[int] = None + metadata_time_ms: Optional[int] = None network_sent_bytes: Optional[int] = None + overloading_queue_start_timestamp: Optional[int] = None photon_total_time_ms: Optional[int] = None - queued_overload_time_ms: Optional[int] = None - queued_provisioning_time_ms: Optional[int] = None + planning_phases: Optional['List[Any]'] = None + planning_time_ms: Optional[int] = None + provisioning_queue_start_timestamp: Optional[int] = None + pruned_bytes: Optional[int] = None + pruned_files_count: Optional[int] = None + query_compilation_start_timestamp: Optional[int] = None + query_execution_time_ms: Optional[int] = None read_bytes: Optional[int] = None read_cache_bytes: Optional[int] = None read_files_count: Optional[int] = None @@ -1674,8 +1712,6 @@ class QueryMetrics: rows_read_count: Optional[int] = None spill_to_disk_bytes: Optional[int] = None task_total_time_ms: Optional[int] = None - total_files_count: Optional[int] = None - total_partitions_count: Optional[int] = None total_time_ms: Optional[int] = None write_remote_bytes: Optional[int] = None @@ -1683,12 +1719,21 @@ def as_dict(self) -> dict: body = {} if self.compilation_time_ms is not None: body['compilation_time_ms'] = self.compilation_time_ms if self.execution_time_ms is not None: body['execution_time_ms'] = self.execution_time_ms + if self.metadata_time_ms is not None: body['metadata_time_ms'] = self.metadata_time_ms if self.network_sent_bytes is not None: body['network_sent_bytes'] = self.network_sent_bytes + if self.overloading_queue_start_timestamp is not None: + body['overloading_queue_start_timestamp'] = self.overloading_queue_start_timestamp if self.photon_total_time_ms is not None: body['photon_total_time_ms'] = self.photon_total_time_ms - if self.queued_overload_time_ms is not None: - body['queued_overload_time_ms'] = self.queued_overload_time_ms - if self.queued_provisioning_time_ms is not None: - body['queued_provisioning_time_ms'] = self.queued_provisioning_time_ms + if self.planning_phases: body['planning_phases'] = [v for v in self.planning_phases] + if self.planning_time_ms is not None: body['planning_time_ms'] = self.planning_time_ms + if self.provisioning_queue_start_timestamp is not None: + body['provisioning_queue_start_timestamp'] = self.provisioning_queue_start_timestamp + if self.pruned_bytes is not None: body['pruned_bytes'] = self.pruned_bytes + if self.pruned_files_count is not None: body['pruned_files_count'] = self.pruned_files_count + if self.query_compilation_start_timestamp is not None: + body['query_compilation_start_timestamp'] = self.query_compilation_start_timestamp + if self.query_execution_time_ms is not None: + body['query_execution_time_ms'] = self.query_execution_time_ms if self.read_bytes is not None: body['read_bytes'] = self.read_bytes if self.read_cache_bytes is not None: body['read_cache_bytes'] = self.read_cache_bytes if self.read_files_count is not None: body['read_files_count'] = self.read_files_count @@ -1700,9 +1745,6 @@ def as_dict(self) -> dict: if self.rows_read_count is not None: body['rows_read_count'] = self.rows_read_count if self.spill_to_disk_bytes is not None: body['spill_to_disk_bytes'] = self.spill_to_disk_bytes if self.task_total_time_ms is not None: body['task_total_time_ms'] = self.task_total_time_ms - if self.total_files_count is not None: body['total_files_count'] = self.total_files_count - if self.total_partitions_count is not None: - body['total_partitions_count'] = self.total_partitions_count if self.total_time_ms is not None: body['total_time_ms'] = self.total_time_ms if self.write_remote_bytes is not None: body['write_remote_bytes'] = self.write_remote_bytes return body @@ -1711,10 +1753,17 @@ def as_dict(self) -> dict: def from_dict(cls, d: Dict[str, any]) -> 'QueryMetrics': return cls(compilation_time_ms=d.get('compilation_time_ms', None), execution_time_ms=d.get('execution_time_ms', None), + metadata_time_ms=d.get('metadata_time_ms', None), network_sent_bytes=d.get('network_sent_bytes', None), + overloading_queue_start_timestamp=d.get('overloading_queue_start_timestamp', None), photon_total_time_ms=d.get('photon_total_time_ms', None), - queued_overload_time_ms=d.get('queued_overload_time_ms', None), - queued_provisioning_time_ms=d.get('queued_provisioning_time_ms', None), + planning_phases=d.get('planning_phases', None), + planning_time_ms=d.get('planning_time_ms', None), + provisioning_queue_start_timestamp=d.get('provisioning_queue_start_timestamp', None), + pruned_bytes=d.get('pruned_bytes', None), + pruned_files_count=d.get('pruned_files_count', None), + query_compilation_start_timestamp=d.get('query_compilation_start_timestamp', None), + query_execution_time_ms=d.get('query_execution_time_ms', None), read_bytes=d.get('read_bytes', None), read_cache_bytes=d.get('read_cache_bytes', None), read_files_count=d.get('read_files_count', None), @@ -1726,8 +1775,6 @@ def from_dict(cls, d: Dict[str, any]) -> 'QueryMetrics': rows_read_count=d.get('rows_read_count', None), spill_to_disk_bytes=d.get('spill_to_disk_bytes', None), task_total_time_ms=d.get('task_total_time_ms', None), - total_files_count=d.get('total_files_count', None), - total_partitions_count=d.get('total_partitions_count', None), total_time_ms=d.get('total_time_ms', None), write_remote_bytes=d.get('write_remote_bytes', None)) @@ -2394,6 +2441,141 @@ def from_dict(cls, d: Dict[str, any]) -> 'Visualization': updated_at=d.get('updated_at', None)) +@dataclass +class WarehouseAccessControlRequest: + group_name: Optional[str] = None + permission_level: Optional['WarehousePermissionLevel'] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'WarehouseAccessControlRequest': + return cls(group_name=d.get('group_name', None), + permission_level=_enum(d, 'permission_level', WarehousePermissionLevel), + service_principal_name=d.get('service_principal_name', None), + user_name=d.get('user_name', None)) + + +@dataclass +class WarehouseAccessControlResponse: + all_permissions: Optional['List[WarehousePermission]'] = None + display_name: Optional[str] = None + group_name: Optional[str] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'WarehouseAccessControlResponse': + return cls(all_permissions=_repeated(d, 'all_permissions', WarehousePermission), + 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 WarehousePermission: + inherited: Optional[bool] = None + inherited_from_object: Optional['List[str]'] = None + permission_level: Optional['WarehousePermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'WarehousePermission': + return cls(inherited=d.get('inherited', None), + inherited_from_object=d.get('inherited_from_object', None), + permission_level=_enum(d, 'permission_level', WarehousePermissionLevel)) + + +class WarehousePermissionLevel(Enum): + """Permission level""" + + CAN_MANAGE = 'CAN_MANAGE' + CAN_USE = 'CAN_USE' + IS_OWNER = 'IS_OWNER' + + +@dataclass +class WarehousePermissions: + access_control_list: Optional['List[WarehouseAccessControlResponse]'] = None + object_id: Optional[str] = None + object_type: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'WarehousePermissions': + return cls(access_control_list=_repeated(d, 'access_control_list', WarehouseAccessControlResponse), + object_id=d.get('object_id', None), + object_type=d.get('object_type', None)) + + +@dataclass +class WarehousePermissionsDescription: + description: Optional[str] = None + permission_level: Optional['WarehousePermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'WarehousePermissionsDescription': + return cls(description=d.get('description', None), + permission_level=_enum(d, 'permission_level', WarehousePermissionLevel)) + + +@dataclass +class WarehousePermissionsRequest: + access_control_list: Optional['List[WarehouseAccessControlRequest]'] = None + warehouse_id: Optional[str] = None + + def as_dict(self) -> dict: + body = {} + if self.access_control_list: + body['access_control_list'] = [v.as_dict() for v in self.access_control_list] + if self.warehouse_id is not None: body['warehouse_id'] = self.warehouse_id + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'WarehousePermissionsRequest': + return cls(access_control_list=_repeated(d, 'access_control_list', WarehouseAccessControlRequest), + warehouse_id=d.get('warehouse_id', None)) + + @dataclass class WarehouseTypePair: enabled: Optional[bool] = None @@ -2421,7 +2603,7 @@ class WarehouseTypePairWarehouseType(Enum): @dataclass class Widget: - id: Optional[int] = None + id: Optional[str] = None options: Optional['WidgetOptions'] = None visualization: Optional['Visualization'] = None width: Optional[int] = None @@ -3829,6 +4011,42 @@ def get(self, id: str, **kwargs) -> GetWarehouseResponse: json = self._api.do('GET', f'/api/2.0/sql/warehouses/{request.id}') return GetWarehouseResponse.from_dict(json) + def get_warehouse_permission_levels(self, warehouse_id: str, + **kwargs) -> GetWarehousePermissionLevelsResponse: + """Get SQL warehouse permission levels. + + Gets the permission levels that a user can have on an object. + + :param warehouse_id: str + The SQL warehouse for which to get or manage permissions. + + :returns: :class:`GetWarehousePermissionLevelsResponse` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetWarehousePermissionLevelsRequest(warehouse_id=warehouse_id) + + json = self._api.do('GET', f'/api/2.0/permissions/warehouses/{request.warehouse_id}/permissionLevels') + return GetWarehousePermissionLevelsResponse.from_dict(json) + + def get_warehouse_permissions(self, warehouse_id: str, **kwargs) -> WarehousePermissions: + """Get SQL warehouse permissions. + + Gets the permissions of a SQL warehouse. SQL warehouses can inherit permissions from their root + object. + + :param warehouse_id: str + The SQL warehouse for which to get or manage permissions. + + :returns: :class:`WarehousePermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetWarehousePermissionsRequest(warehouse_id=warehouse_id) + + json = self._api.do('GET', f'/api/2.0/permissions/warehouses/{request.warehouse_id}') + return WarehousePermissions.from_dict(json) + def get_workspace_warehouse_config(self) -> GetWorkspaceWarehouseConfigResponse: """Get the workspace configuration. @@ -3861,6 +4079,30 @@ def list(self, *, run_as_user_id: Optional[int] = None, **kwargs) -> Iterator[En json = self._api.do('GET', '/api/2.0/sql/warehouses', query=query) return [EndpointInfo.from_dict(v) for v in json.get('warehouses', [])] + def set_warehouse_permissions(self, + warehouse_id: str, + *, + access_control_list: Optional[List[WarehouseAccessControlRequest]] = None, + **kwargs) -> WarehousePermissions: + """Set SQL warehouse permissions. + + Sets permissions on a SQL warehouse. SQL warehouses can inherit permissions from their root object. + + :param warehouse_id: str + The SQL warehouse for which to get or manage permissions. + :param access_control_list: List[:class:`WarehouseAccessControlRequest`] (optional) + + :returns: :class:`WarehousePermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = WarehousePermissionsRequest(access_control_list=access_control_list, + warehouse_id=warehouse_id) + body = request.as_dict() + + json = self._api.do('PUT', f'/api/2.0/permissions/warehouses/{request.warehouse_id}', body=body) + return WarehousePermissions.from_dict(json) + def set_workspace_warehouse_config( self, *, @@ -3961,3 +4203,29 @@ def stop(self, id: str, **kwargs) -> Wait[GetWarehouseResponse]: def stop_and_wait(self, id: str, timeout=timedelta(minutes=20)) -> GetWarehouseResponse: return self.stop(id=id).result(timeout=timeout) + + def update_warehouse_permissions(self, + warehouse_id: str, + *, + access_control_list: Optional[ + List[WarehouseAccessControlRequest]] = None, + **kwargs) -> WarehousePermissions: + """Update SQL warehouse permissions. + + Updates the permissions on a SQL warehouse. SQL warehouses can inherit permissions from their root + object. + + :param warehouse_id: str + The SQL warehouse for which to get or manage permissions. + :param access_control_list: List[:class:`WarehouseAccessControlRequest`] (optional) + + :returns: :class:`WarehousePermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = WarehousePermissionsRequest(access_control_list=access_control_list, + warehouse_id=warehouse_id) + body = request.as_dict() + + json = self._api.do('PATCH', f'/api/2.0/permissions/warehouses/{request.warehouse_id}', body=body) + return WarehousePermissions.from_dict(json) diff --git a/databricks/sdk/service/workspace.py b/databricks/sdk/service/workspace.py index 496e8c88..e62b9b35 100755 --- a/databricks/sdk/service/workspace.py +++ b/databricks/sdk/service/workspace.py @@ -295,6 +295,34 @@ class GetGitCredentialRequest: credential_id: int +@dataclass +class GetRepoPermissionLevelsRequest: + """Get repo permission levels""" + + repo_id: str + + +@dataclass +class GetRepoPermissionLevelsResponse: + permission_levels: Optional['List[RepoPermissionsDescription]'] = None + + def as_dict(self) -> dict: + body = {} + if self.permission_levels: body['permission_levels'] = [v.as_dict() for v in self.permission_levels] + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'GetRepoPermissionLevelsResponse': + return cls(permission_levels=_repeated(d, 'permission_levels', RepoPermissionsDescription)) + + +@dataclass +class GetRepoPermissionsRequest: + """Get repo permissions""" + + repo_id: str + + @dataclass class GetRepoRequest: """Get a repo""" @@ -309,6 +337,36 @@ class GetStatusRequest: path: str +@dataclass +class GetWorkspaceObjectPermissionLevelsRequest: + """Get workspace object permission levels""" + + workspace_object_type: str + workspace_object_id: str + + +@dataclass +class GetWorkspaceObjectPermissionLevelsResponse: + permission_levels: Optional['List[WorkspaceObjectPermissionsDescription]'] = None + + def as_dict(self) -> dict: + body = {} + if self.permission_levels: body['permission_levels'] = [v.as_dict() for v in self.permission_levels] + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'GetWorkspaceObjectPermissionLevelsResponse': + return cls(permission_levels=_repeated(d, 'permission_levels', WorkspaceObjectPermissionsDescription)) + + +@dataclass +class GetWorkspaceObjectPermissionsRequest: + """Get workspace object permissions""" + + workspace_object_type: str + workspace_object_id: str + + @dataclass class Import: path: str @@ -568,6 +626,57 @@ def from_dict(cls, d: Dict[str, any]) -> 'PutSecret': string_value=d.get('string_value', None)) +@dataclass +class RepoAccessControlRequest: + group_name: Optional[str] = None + permission_level: Optional['RepoPermissionLevel'] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'RepoAccessControlRequest': + return cls(group_name=d.get('group_name', None), + permission_level=_enum(d, 'permission_level', RepoPermissionLevel), + service_principal_name=d.get('service_principal_name', None), + user_name=d.get('user_name', None)) + + +@dataclass +class RepoAccessControlResponse: + all_permissions: Optional['List[RepoPermission]'] = None + display_name: Optional[str] = None + group_name: Optional[str] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'RepoAccessControlResponse': + return cls(all_permissions=_repeated(d, 'all_permissions', RepoPermission), + 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 RepoInfo: branch: Optional[str] = None @@ -600,6 +709,91 @@ def from_dict(cls, d: Dict[str, any]) -> 'RepoInfo': url=d.get('url', None)) +@dataclass +class RepoPermission: + inherited: Optional[bool] = None + inherited_from_object: Optional['List[str]'] = None + permission_level: Optional['RepoPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'RepoPermission': + return cls(inherited=d.get('inherited', None), + inherited_from_object=d.get('inherited_from_object', None), + permission_level=_enum(d, 'permission_level', RepoPermissionLevel)) + + +class RepoPermissionLevel(Enum): + """Permission level""" + + CAN_EDIT = 'CAN_EDIT' + CAN_MANAGE = 'CAN_MANAGE' + CAN_READ = 'CAN_READ' + CAN_RUN = 'CAN_RUN' + + +@dataclass +class RepoPermissions: + access_control_list: Optional['List[RepoAccessControlResponse]'] = None + object_id: Optional[str] = None + object_type: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'RepoPermissions': + return cls(access_control_list=_repeated(d, 'access_control_list', RepoAccessControlResponse), + object_id=d.get('object_id', None), + object_type=d.get('object_type', None)) + + +@dataclass +class RepoPermissionsDescription: + description: Optional[str] = None + permission_level: Optional['RepoPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'RepoPermissionsDescription': + return cls(description=d.get('description', None), + permission_level=_enum(d, 'permission_level', RepoPermissionLevel)) + + +@dataclass +class RepoPermissionsRequest: + access_control_list: Optional['List[RepoAccessControlRequest]'] = None + repo_id: Optional[str] = None + + def as_dict(self) -> dict: + body = {} + if self.access_control_list: + body['access_control_list'] = [v.as_dict() for v in self.access_control_list] + if self.repo_id is not None: body['repo_id'] = self.repo_id + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'RepoPermissionsRequest': + return cls(access_control_list=_repeated(d, 'access_control_list', RepoAccessControlRequest), + repo_id=d.get('repo_id', None)) + + class ScopeBackendType(Enum): AZURE_KEYVAULT = 'AZURE_KEYVAULT' @@ -717,6 +911,147 @@ def from_dict(cls, d: Dict[str, any]) -> 'UpdateRepo': tag=d.get('tag', None)) +@dataclass +class WorkspaceObjectAccessControlRequest: + group_name: Optional[str] = None + permission_level: Optional['WorkspaceObjectPermissionLevel'] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'WorkspaceObjectAccessControlRequest': + return cls(group_name=d.get('group_name', None), + permission_level=_enum(d, 'permission_level', WorkspaceObjectPermissionLevel), + service_principal_name=d.get('service_principal_name', None), + user_name=d.get('user_name', None)) + + +@dataclass +class WorkspaceObjectAccessControlResponse: + all_permissions: Optional['List[WorkspaceObjectPermission]'] = None + display_name: Optional[str] = None + group_name: Optional[str] = None + service_principal_name: Optional[str] = None + user_name: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'WorkspaceObjectAccessControlResponse': + return cls(all_permissions=_repeated(d, 'all_permissions', WorkspaceObjectPermission), + 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 WorkspaceObjectPermission: + inherited: Optional[bool] = None + inherited_from_object: Optional['List[str]'] = None + permission_level: Optional['WorkspaceObjectPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'WorkspaceObjectPermission': + return cls(inherited=d.get('inherited', None), + inherited_from_object=d.get('inherited_from_object', None), + permission_level=_enum(d, 'permission_level', WorkspaceObjectPermissionLevel)) + + +class WorkspaceObjectPermissionLevel(Enum): + """Permission level""" + + CAN_EDIT = 'CAN_EDIT' + CAN_MANAGE = 'CAN_MANAGE' + CAN_READ = 'CAN_READ' + CAN_RUN = 'CAN_RUN' + + +@dataclass +class WorkspaceObjectPermissions: + access_control_list: Optional['List[WorkspaceObjectAccessControlResponse]'] = None + object_id: Optional[str] = None + object_type: Optional[str] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'WorkspaceObjectPermissions': + return cls(access_control_list=_repeated(d, 'access_control_list', + WorkspaceObjectAccessControlResponse), + object_id=d.get('object_id', None), + object_type=d.get('object_type', None)) + + +@dataclass +class WorkspaceObjectPermissionsDescription: + description: Optional[str] = None + permission_level: Optional['WorkspaceObjectPermissionLevel'] = None + + def as_dict(self) -> dict: + 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 + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'WorkspaceObjectPermissionsDescription': + return cls(description=d.get('description', None), + permission_level=_enum(d, 'permission_level', WorkspaceObjectPermissionLevel)) + + +@dataclass +class WorkspaceObjectPermissionsRequest: + access_control_list: Optional['List[WorkspaceObjectAccessControlRequest]'] = None + workspace_object_id: Optional[str] = None + workspace_object_type: Optional[str] = None + + def as_dict(self) -> dict: + body = {} + if self.access_control_list: + body['access_control_list'] = [v.as_dict() for v in self.access_control_list] + if self.workspace_object_id is not None: body['workspace_object_id'] = self.workspace_object_id + if self.workspace_object_type is not None: body['workspace_object_type'] = self.workspace_object_type + return body + + @classmethod + def from_dict(cls, d: Dict[str, any]) -> 'WorkspaceObjectPermissionsRequest': + return cls(access_control_list=_repeated(d, 'access_control_list', + WorkspaceObjectAccessControlRequest), + workspace_object_id=d.get('workspace_object_id', None), + workspace_object_type=d.get('workspace_object_type', None)) + + class GitCredentialsAPI: """Registers personal access token for Databricks to do operations on behalf of the user. @@ -919,6 +1254,40 @@ def get(self, repo_id: int, **kwargs) -> RepoInfo: json = self._api.do('GET', f'/api/2.0/repos/{request.repo_id}') return RepoInfo.from_dict(json) + def get_repo_permission_levels(self, repo_id: str, **kwargs) -> GetRepoPermissionLevelsResponse: + """Get repo permission levels. + + Gets the permission levels that a user can have on an object. + + :param repo_id: str + The repo for which to get or manage permissions. + + :returns: :class:`GetRepoPermissionLevelsResponse` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetRepoPermissionLevelsRequest(repo_id=repo_id) + + json = self._api.do('GET', f'/api/2.0/permissions/repos/{request.repo_id}/permissionLevels') + return GetRepoPermissionLevelsResponse.from_dict(json) + + def get_repo_permissions(self, repo_id: str, **kwargs) -> RepoPermissions: + """Get repo permissions. + + Gets the permissions of a repo. Repos can inherit permissions from their root object. + + :param repo_id: str + The repo for which to get or manage permissions. + + :returns: :class:`RepoPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetRepoPermissionsRequest(repo_id=repo_id) + + json = self._api.do('GET', f'/api/2.0/permissions/repos/{request.repo_id}') + return RepoPermissions.from_dict(json) + def list(self, *, next_page_token: Optional[str] = None, @@ -955,6 +1324,29 @@ def list(self, return query['next_page_token'] = json['next_page_token'] + def set_repo_permissions(self, + repo_id: str, + *, + access_control_list: Optional[List[RepoAccessControlRequest]] = None, + **kwargs) -> RepoPermissions: + """Set repo permissions. + + Sets permissions on a repo. Repos can inherit permissions from their root object. + + :param repo_id: str + The repo for which to get or manage permissions. + :param access_control_list: List[:class:`RepoAccessControlRequest`] (optional) + + :returns: :class:`RepoPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = RepoPermissionsRequest(access_control_list=access_control_list, repo_id=repo_id) + body = request.as_dict() + + json = self._api.do('PUT', f'/api/2.0/permissions/repos/{request.repo_id}', body=body) + return RepoPermissions.from_dict(json) + def update(self, repo_id: int, *, @@ -987,6 +1379,29 @@ def update(self, body = request.as_dict() self._api.do('PATCH', f'/api/2.0/repos/{request.repo_id}', body=body) + def update_repo_permissions(self, + repo_id: str, + *, + access_control_list: Optional[List[RepoAccessControlRequest]] = None, + **kwargs) -> RepoPermissions: + """Update repo permissions. + + Updates the permissions on a repo. Repos can inherit permissions from their root object. + + :param repo_id: str + The repo for which to get or manage permissions. + :param access_control_list: List[:class:`RepoAccessControlRequest`] (optional) + + :returns: :class:`RepoPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = RepoPermissionsRequest(access_control_list=access_control_list, repo_id=repo_id) + body = request.as_dict() + + json = self._api.do('PATCH', f'/api/2.0/permissions/repos/{request.repo_id}', body=body) + return RepoPermissions.from_dict(json) + class SecretsAPI: """The Secrets API allows you to manage secrets, secret scopes, and access permissions. @@ -1362,6 +1777,53 @@ def get_status(self, path: str, **kwargs) -> ObjectInfo: json = self._api.do('GET', '/api/2.0/workspace/get-status', query=query) return ObjectInfo.from_dict(json) + def get_workspace_object_permission_levels(self, workspace_object_type: str, workspace_object_id: str, + **kwargs) -> GetWorkspaceObjectPermissionLevelsResponse: + """Get workspace object permission levels. + + Gets the permission levels that a user can have on an object. + + :param workspace_object_type: str + The workspace object type for which to get or manage permissions. + :param workspace_object_id: str + The workspace object for which to get or manage permissions. + + :returns: :class:`GetWorkspaceObjectPermissionLevelsResponse` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetWorkspaceObjectPermissionLevelsRequest(workspace_object_id=workspace_object_id, + workspace_object_type=workspace_object_type) + + json = self._api.do( + 'GET', + f'/api/2.0/permissions/{request.workspace_object_type}/{request.workspace_object_id}/permissionLevels' + ) + return GetWorkspaceObjectPermissionLevelsResponse.from_dict(json) + + def get_workspace_object_permissions(self, workspace_object_type: str, workspace_object_id: str, + **kwargs) -> WorkspaceObjectPermissions: + """Get workspace object permissions. + + Gets the permissions of a workspace object. Workspace objects can inherit permissions from their + parent objects or root object. + + :param workspace_object_type: str + The workspace object type for which to get or manage permissions. + :param workspace_object_id: str + The workspace object for which to get or manage permissions. + + :returns: :class:`WorkspaceObjectPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = GetWorkspaceObjectPermissionsRequest(workspace_object_id=workspace_object_id, + workspace_object_type=workspace_object_type) + + json = self._api.do( + 'GET', f'/api/2.0/permissions/{request.workspace_object_type}/{request.workspace_object_id}') + return WorkspaceObjectPermissions.from_dict(json) + def import_(self, path: str, *, @@ -1462,3 +1924,69 @@ def mkdirs(self, path: str, **kwargs): request = Mkdirs(path=path) body = request.as_dict() self._api.do('POST', '/api/2.0/workspace/mkdirs', body=body) + + def set_workspace_object_permissions(self, + workspace_object_type: str, + workspace_object_id: str, + *, + access_control_list: Optional[ + List[WorkspaceObjectAccessControlRequest]] = None, + **kwargs) -> WorkspaceObjectPermissions: + """Set workspace object permissions. + + Sets permissions on a workspace object. Workspace objects can inherit permissions from their parent + objects or root object. + + :param workspace_object_type: str + The workspace object type for which to get or manage permissions. + :param workspace_object_id: str + The workspace object for which to get or manage permissions. + :param access_control_list: List[:class:`WorkspaceObjectAccessControlRequest`] (optional) + + :returns: :class:`WorkspaceObjectPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = WorkspaceObjectPermissionsRequest(access_control_list=access_control_list, + workspace_object_id=workspace_object_id, + workspace_object_type=workspace_object_type) + body = request.as_dict() + + json = self._api.do( + 'PUT', + f'/api/2.0/permissions/{request.workspace_object_type}/{request.workspace_object_id}', + body=body) + return WorkspaceObjectPermissions.from_dict(json) + + def update_workspace_object_permissions(self, + workspace_object_type: str, + workspace_object_id: str, + *, + access_control_list: Optional[ + List[WorkspaceObjectAccessControlRequest]] = None, + **kwargs) -> WorkspaceObjectPermissions: + """Update workspace object permissions. + + Updates the permissions on a workspace object. Workspace objects can inherit permissions from their + parent objects or root object. + + :param workspace_object_type: str + The workspace object type for which to get or manage permissions. + :param workspace_object_id: str + The workspace object for which to get or manage permissions. + :param access_control_list: List[:class:`WorkspaceObjectAccessControlRequest`] (optional) + + :returns: :class:`WorkspaceObjectPermissions` + """ + request = kwargs.get('request', None) + if not request: # request is not given through keyed args + request = WorkspaceObjectPermissionsRequest(access_control_list=access_control_list, + workspace_object_id=workspace_object_id, + workspace_object_type=workspace_object_type) + body = request.as_dict() + + json = self._api.do( + 'PATCH', + f'/api/2.0/permissions/{request.workspace_object_type}/{request.workspace_object_id}', + body=body) + return WorkspaceObjectPermissions.from_dict(json) diff --git a/docs/account/custom_app_integration.rst b/docs/account/custom_app_integration.rst index 656a2002..6a811a77 100644 --- a/docs/account/custom_app_integration.rst +++ b/docs/account/custom_app_integration.rst @@ -8,7 +8,7 @@ OAuth Custom App Integration **Note:** You can only add/use the OAuth custom application integrations when OAuth enrollment status is enabled. For more details see :method:OAuthEnrollment/create - .. py:method:: create(name, redirect_urls [, confidential, token_access_policy]) + .. py:method:: create(name, redirect_urls [, confidential, scopes, token_access_policy]) Create Custom OAuth App Integration. @@ -22,6 +22,9 @@ OAuth Custom App Integration List of oauth redirect urls :param confidential: bool (optional) indicates if an oauth client-secret should be generated + :param scopes: List[str] (optional) + OAuth scopes granted to the application. Supported scopes: all-apis, sql, offline_access, openid, + profile, email. :param token_access_policy: :class:`TokenAccessPolicy` (optional) Token access policy diff --git a/docs/account/workspaces.rst b/docs/account/workspaces.rst index 2e9347da..7225f776 100644 --- a/docs/account/workspaces.rst +++ b/docs/account/workspaces.rst @@ -9,7 +9,7 @@ Workspaces These endpoints are available if your account is on the E2 version of the platform or on a select custom plan that allows multiple workspaces per account. - .. py:method:: create(workspace_name [, aws_region, cloud, cloud_resource_container, credentials_id, deployment_name, location, managed_services_customer_managed_key_id, network_id, pricing_tier, private_access_settings_id, storage_configuration_id, storage_customer_managed_key_id]) + .. py:method:: create(workspace_name [, aws_region, cloud, cloud_resource_container, credentials_id, deployment_name, gcp_managed_network_config, gke_config, location, managed_services_customer_managed_key_id, network_id, pricing_tier, private_access_settings_id, storage_configuration_id, storage_customer_managed_key_id]) Usage: @@ -90,6 +90,27 @@ Workspaces If a new workspace omits this property, the server generates a unique deployment name for you with the pattern `dbc-xxxxxxxx-xxxx`. + :param gcp_managed_network_config: :class:`GcpManagedNetworkConfig` (optional) + The network settings for the workspace. The configurations are only for Databricks-managed VPCs. It + is ignored if you specify a customer-managed VPC in the `network_id` field.", All the IP range + configurations must be mutually exclusive. An attempt to create a workspace fails if Databricks + detects an IP range overlap. + + Specify custom IP ranges in CIDR format. The IP ranges for these fields must not overlap, and all IP + addresses must be entirely within the following ranges: `10.0.0.0/8`, `100.64.0.0/10`, + `172.16.0.0/12`, `192.168.0.0/16`, and `240.0.0.0/4`. + + The sizes of these IP ranges affect the maximum number of nodes for the workspace. + + **Important**: Confirm the IP ranges used by your Databricks workspace before creating the + workspace. You cannot change them after your workspace is deployed. If the IP address ranges for + your Databricks are too small, IP exhaustion can occur, causing your Databricks jobs to fail. To + determine the address range sizes that you need, Databricks provides a calculator as a Microsoft + Excel spreadsheet. See [calculate subnet sizes for a new workspace]. + + [calculate subnet sizes for a new workspace]: https://docs.gcp.databricks.com/administration-guide/cloud-configurations/gcp/network-sizing.html + :param gke_config: :class:`GkeConfig` (optional) + The configurations for the GKE cluster of a Databricks workspace. :param location: str (optional) The Google Cloud region of the workspace data plane in your Google account. For example, `us-east4`. :param managed_services_customer_managed_key_id: str (optional) diff --git a/docs/workspace/cluster_policies.rst b/docs/workspace/cluster_policies.rst index 534e3928..9826482a 100644 --- a/docs/workspace/cluster_policies.rst +++ b/docs/workspace/cluster_policies.rst @@ -192,6 +192,31 @@ Cluster Policies :returns: :class:`Policy` + .. py:method:: get_cluster_policy_permission_levels(cluster_policy_id) + + Get cluster policy permission levels. + + Gets the permission levels that a user can have on an object. + + :param cluster_policy_id: str + The cluster policy for which to get or manage permissions. + + :returns: :class:`GetClusterPolicyPermissionLevelsResponse` + + + .. py:method:: get_cluster_policy_permissions(cluster_policy_id) + + Get cluster policy permissions. + + Gets the permissions of a cluster policy. Cluster policies can inherit permissions from their root + object. + + :param cluster_policy_id: str + The cluster policy for which to get or manage permissions. + + :returns: :class:`ClusterPolicyPermissions` + + .. py:method:: list( [, sort_column, sort_order]) Usage: @@ -217,4 +242,31 @@ Cluster Policies - Sort result list in ascending order. :returns: Iterator over :class:`Policy` + + + .. py:method:: set_cluster_policy_permissions(cluster_policy_id [, access_control_list]) + + Set cluster policy permissions. + + Sets permissions on a cluster policy. Cluster policies can inherit permissions from their root object. + + :param cluster_policy_id: str + The cluster policy for which to get or manage permissions. + :param access_control_list: List[:class:`ClusterPolicyAccessControlRequest`] (optional) + + :returns: :class:`ClusterPolicyPermissions` + + + .. py:method:: update_cluster_policy_permissions(cluster_policy_id [, access_control_list]) + + Update cluster policy permissions. + + Updates the permissions on a cluster policy. Cluster policies can inherit permissions from their root + object. + + :param cluster_policy_id: str + The cluster policy for which to get or manage permissions. + :param access_control_list: List[:class:`ClusterPolicyAccessControlRequest`] (optional) + + :returns: :class:`ClusterPolicyPermissions` \ No newline at end of file diff --git a/docs/workspace/clusters.rst b/docs/workspace/clusters.rst index 7243f761..37f08be6 100644 --- a/docs/workspace/clusters.rst +++ b/docs/workspace/clusters.rst @@ -523,6 +523,30 @@ Clusters :returns: :class:`ClusterDetails` + .. py:method:: get_cluster_permission_levels(cluster_id) + + Get cluster permission levels. + + Gets the permission levels that a user can have on an object. + + :param cluster_id: str + The cluster for which to get or manage permissions. + + :returns: :class:`GetClusterPermissionLevelsResponse` + + + .. py:method:: get_cluster_permissions(cluster_id) + + Get cluster permissions. + + Gets the permissions of a cluster. Clusters can inherit permissions from their root object. + + :param cluster_id: str + The cluster for which to get or manage permissions. + + :returns: :class:`ClusterPermissions` + + .. py:method:: list( [, can_use_client]) Usage: @@ -791,6 +815,19 @@ Clusters :returns: `spark_version` compatible string + .. py:method:: set_cluster_permissions(cluster_id [, access_control_list]) + + Set cluster permissions. + + Sets permissions on a cluster. Clusters can inherit permissions from their root object. + + :param cluster_id: str + The cluster for which to get or manage permissions. + :param access_control_list: List[:class:`ClusterAccessControlRequest`] (optional) + + :returns: :class:`ClusterPermissions` + + .. py:method:: spark_versions() List available Spark versions. @@ -883,4 +920,17 @@ Clusters + + + .. py:method:: update_cluster_permissions(cluster_id [, access_control_list]) + + Update cluster permissions. + + Updates the permissions on a cluster. Clusters can inherit permissions from their root object. + + :param cluster_id: str + The cluster for which to get or manage permissions. + :param access_control_list: List[:class:`ClusterAccessControlRequest`] (optional) + + :returns: :class:`ClusterPermissions` \ No newline at end of file diff --git a/docs/workspace/experiments.rst b/docs/workspace/experiments.rst index bba64dbf..e0491759 100644 --- a/docs/workspace/experiments.rst +++ b/docs/workspace/experiments.rst @@ -176,6 +176,30 @@ Experiments :returns: :class:`Experiment` + .. py:method:: get_experiment_permission_levels(experiment_id) + + Get experiment permission levels. + + Gets the permission levels that a user can have on an object. + + :param experiment_id: str + The experiment for which to get or manage permissions. + + :returns: :class:`GetExperimentPermissionLevelsResponse` + + + .. py:method:: get_experiment_permissions(experiment_id) + + Get experiment permissions. + + Gets the permissions of an experiment. Experiments can inherit permissions from their root object. + + :param experiment_id: str + The experiment for which to get or manage permissions. + + :returns: :class:`ExperimentPermissions` + + .. py:method:: get_history(metric_key [, max_results, page_token, run_id, run_uuid]) Get history of a given metric within a run. @@ -480,6 +504,19 @@ Experiments :returns: Iterator over :class:`Run` + .. py:method:: set_experiment_permissions(experiment_id [, access_control_list]) + + Set experiment permissions. + + Sets permissions on an experiment. Experiments can inherit permissions from their root object. + + :param experiment_id: str + The experiment for which to get or manage permissions. + :param access_control_list: List[:class:`ExperimentAccessControlRequest`] (optional) + + :returns: :class:`ExperimentPermissions` + + .. py:method:: set_experiment_tag(experiment_id, key, value) Set a tag. @@ -550,6 +587,19 @@ Experiments + .. py:method:: update_experiment_permissions(experiment_id [, access_control_list]) + + Update experiment permissions. + + Updates the permissions on an experiment. Experiments can inherit permissions from their root object. + + :param experiment_id: str + The experiment for which to get or manage permissions. + :param access_control_list: List[:class:`ExperimentAccessControlRequest`] (optional) + + :returns: :class:`ExperimentPermissions` + + .. py:method:: update_run( [, end_time, run_id, run_uuid, status]) Usage: diff --git a/docs/workspace/instance_pools.rst b/docs/workspace/instance_pools.rst index e4e92a65..6b11c3c2 100644 --- a/docs/workspace/instance_pools.rst +++ b/docs/workspace/instance_pools.rst @@ -216,6 +216,31 @@ Instance Pools :returns: :class:`GetInstancePool` + .. py:method:: get_instance_pool_permission_levels(instance_pool_id) + + Get instance pool permission levels. + + Gets the permission levels that a user can have on an object. + + :param instance_pool_id: str + The instance pool for which to get or manage permissions. + + :returns: :class:`GetInstancePoolPermissionLevelsResponse` + + + .. py:method:: get_instance_pool_permissions(instance_pool_id) + + Get instance pool permissions. + + Gets the permissions of an instance pool. Instance pools can inherit permissions from their root + object. + + :param instance_pool_id: str + The instance pool for which to get or manage permissions. + + :returns: :class:`InstancePoolPermissions` + + .. py:method:: list() Usage: @@ -233,4 +258,31 @@ Instance Pools Gets a list of instance pools with their statistics. :returns: Iterator over :class:`InstancePoolAndStats` + + + .. py:method:: set_instance_pool_permissions(instance_pool_id [, access_control_list]) + + Set instance pool permissions. + + Sets permissions on an instance pool. Instance pools can inherit permissions from their root object. + + :param instance_pool_id: str + The instance pool for which to get or manage permissions. + :param access_control_list: List[:class:`InstancePoolAccessControlRequest`] (optional) + + :returns: :class:`InstancePoolPermissions` + + + .. py:method:: update_instance_pool_permissions(instance_pool_id [, access_control_list]) + + Update instance pool permissions. + + Updates the permissions on an instance pool. Instance pools can inherit permissions from their root + object. + + :param instance_pool_id: str + The instance pool for which to get or manage permissions. + :param access_control_list: List[:class:`InstancePoolAccessControlRequest`] (optional) + + :returns: :class:`InstancePoolPermissions` \ No newline at end of file diff --git a/docs/workspace/jobs.rst b/docs/workspace/jobs.rst index cea15c51..ac71f6d5 100644 --- a/docs/workspace/jobs.rst +++ b/docs/workspace/jobs.rst @@ -328,6 +328,30 @@ Jobs :returns: :class:`Job` + .. py:method:: get_job_permission_levels(job_id) + + Get job permission levels. + + Gets the permission levels that a user can have on an object. + + :param job_id: str + The job for which to get or manage permissions. + + :returns: :class:`GetJobPermissionLevelsResponse` + + + .. py:method:: get_job_permissions(job_id) + + Get job permissions. + + Gets the permissions of a job. Jobs can inherit permissions from their root object. + + :param job_id: str + The job for which to get or manage permissions. + + :returns: :class:`JobPermissions` + + .. py:method:: get_run(run_id [, include_history]) Usage: @@ -798,6 +822,19 @@ Jobs See :method:wait_get_run_job_terminated_or_skipped for more details. + .. py:method:: set_job_permissions(job_id [, access_control_list]) + + Set job permissions. + + Sets permissions on a job. Jobs can inherit permissions from their root object. + + :param job_id: str + The job for which to get or manage permissions. + :param access_control_list: List[:class:`JobAccessControlRequest`] (optional) + + :returns: :class:`JobPermissions` + + .. py:method:: submit( [, access_control_list, email_notifications, git_source, health, idempotency_token, notification_settings, run_name, tasks, timeout_seconds, webhook_notifications]) Usage: @@ -931,4 +968,17 @@ Jobs fields are applied to future runs only. + + + .. py:method:: update_job_permissions(job_id [, access_control_list]) + + Update job permissions. + + Updates the permissions on a job. Jobs can inherit permissions from their root object. + + :param job_id: str + The job for which to get or manage permissions. + :param access_control_list: List[:class:`JobAccessControlRequest`] (optional) + + :returns: :class:`JobPermissions` \ No newline at end of file diff --git a/docs/workspace/model_registry.rst b/docs/workspace/model_registry.rst index 4ebd924d..4d2ff447 100644 --- a/docs/workspace/model_registry.rst +++ b/docs/workspace/model_registry.rst @@ -416,6 +416,31 @@ Model Registry :returns: :class:`GetModelVersionDownloadUriResponse` + .. py:method:: get_registered_model_permission_levels(registered_model_id) + + Get registered model permission levels. + + Gets the permission levels that a user can have on an object. + + :param registered_model_id: str + The registered model for which to get or manage permissions. + + :returns: :class:`GetRegisteredModelPermissionLevelsResponse` + + + .. py:method:: get_registered_model_permissions(registered_model_id) + + Get registered model permissions. + + Gets the permissions of a registered model. Registered models can inherit permissions from their root + object. + + :param registered_model_id: str + The registered model for which to get or manage permissions. + + :returns: :class:`RegisteredModelPermissions` + + .. py:method:: list_models( [, max_results, page_token]) Usage: @@ -609,6 +634,20 @@ Model Registry + .. py:method:: set_registered_model_permissions(registered_model_id [, access_control_list]) + + Set registered model permissions. + + Sets permissions on a registered model. Registered models can inherit permissions from their root + object. + + :param registered_model_id: str + The registered model for which to get or manage permissions. + :param access_control_list: List[:class:`RegisteredModelAccessControlRequest`] (optional) + + :returns: :class:`RegisteredModelPermissions` + + .. py:method:: test_registry_webhook(id [, event]) Test a webhook. @@ -760,6 +799,20 @@ Model Registry + .. py:method:: update_registered_model_permissions(registered_model_id [, access_control_list]) + + Update registered model permissions. + + Updates the permissions on a registered model. Registered models can inherit permissions from their + root object. + + :param registered_model_id: str + The registered model for which to get or manage permissions. + :param access_control_list: List[:class:`RegisteredModelAccessControlRequest`] (optional) + + :returns: :class:`RegisteredModelPermissions` + + .. py:method:: update_webhook(id [, description, events, http_url_spec, job_spec, status]) Usage: diff --git a/docs/workspace/permissions.rst b/docs/workspace/permissions.rst index f88a17e4..b2cdbe0c 100644 --- a/docs/workspace/permissions.rst +++ b/docs/workspace/permissions.rst @@ -4,6 +4,48 @@ Permissions Permissions API are used to create read, write, edit, update and manage access for various users on different objects and endpoints. + + * **[Cluster permissions](:service:clusters)** — Manage which users can manage, restart, or attach to + clusters. + + * **[Cluster policy permissions](:service:clusterpolicies)** — Manage which users can use cluster + policies. + + * **[Delta Live Tables pipeline permissions](:service:pipelines)** — Manage which users can view, + manage, run, cancel, or own a Delta Live Tables pipeline. + + * **[Job permissions](:service:jobs)** — Manage which users can view, manage, trigger, cancel, or own a + job. + + * **[MLflow experiment permissions](:service:experiments)** — Manage which users can read, edit, or + manage MLflow experiments. + + * **[MLflow registered model permissions](:service:modelregistry)** — Manage which users can read, edit, + or manage MLflow registered models. + + * **[Password permissions](:service:users)** — Manage which users can use password login when SSO is + enabled. + + * **[Instance Pool permissions](:service:instancepools)** — Manage which users can manage or attach to + pools. + + * **[Repo permissions](repos)** — Manage which users can read, run, edit, or manage a repo. + + * **[Serving endpoint permissions](:service:servingendpoints)** — Manage which users can view, query, or + manage a serving endpoint. + + * **[SQL warehouse permissions](:service:warehouses)** — Manage which users can use or manage SQL + warehouses. + + * **[Token permissions](:service:tokenmanagement)** — Manage which users can create or use tokens. + + * **[Workspace object permissions](:service:workspace)** — Manage which users can read, run, edit, or + manage directories, files, and notebooks. + + For the mapping of the required permissions for specific actions or abilities and other important + information, see [Access Control]. + + [Access Control]: https://docs.databricks.com/security/auth-authz/access-control/index.html .. py:method:: get(request_object_type, request_object_id) @@ -26,8 +68,8 @@ Permissions Get object permissions. - Gets the permission of an object. Objects can inherit permissions from their parent objects or root - objects. + Gets the permissions of an object. Objects can inherit permissions from their parent objects or root + object. :param request_object_type: str @@ -55,7 +97,7 @@ Permissions levels = w.permissions.get_permission_levels(request_object_type="notebooks", request_object_id="%d" % (obj.object_id)) - Get permission levels. + Get object permission levels. Gets the permission levels that a user can have on an object. @@ -96,29 +138,30 @@ Permissions # cleanup w.groups.delete(id=group.id) - Set permissions. + Set object permissions. - Sets permissions on object. Objects can inherit permissions from their parent objects and root - objects. + Sets permissions on an object. Objects can inherit permissions from their parent objects or root + object. :param request_object_type: str :param request_object_id: str :param access_control_list: List[:class:`AccessControlRequest`] (optional) - + :returns: :class:`ObjectPermissions` .. py:method:: update(request_object_type, request_object_id [, access_control_list]) - Update permission. + Update object permissions. - Updates the permissions on an object. + Updates the permissions on an object. Objects can inherit permissions from their parent objects or + root object. :param request_object_type: str :param request_object_id: str :param access_control_list: List[:class:`AccessControlRequest`] (optional) - + :returns: :class:`ObjectPermissions` \ No newline at end of file diff --git a/docs/workspace/pipelines.rst b/docs/workspace/pipelines.rst index bd92ee0a..0d9a34e2 100644 --- a/docs/workspace/pipelines.rst +++ b/docs/workspace/pipelines.rst @@ -144,6 +144,30 @@ Pipelines :returns: :class:`GetPipelineResponse` + .. py:method:: get_pipeline_permission_levels(pipeline_id) + + Get pipeline permission levels. + + Gets the permission levels that a user can have on an object. + + :param pipeline_id: str + The pipeline for which to get or manage permissions. + + :returns: :class:`GetPipelinePermissionLevelsResponse` + + + .. py:method:: get_pipeline_permissions(pipeline_id) + + Get pipeline permissions. + + Gets the permissions of a pipeline. Pipelines can inherit permissions from their root object. + + :param pipeline_id: str + The pipeline for which to get or manage permissions. + + :returns: :class:`PipelinePermissions` + + .. py:method:: get_update(pipeline_id, update_id) Get a pipeline update. @@ -289,6 +313,19 @@ Pipelines See :method:wait_get_pipeline_running for more details. + .. py:method:: set_pipeline_permissions(pipeline_id [, access_control_list]) + + Set pipeline permissions. + + Sets permissions on a pipeline. Pipelines can inherit permissions from their root object. + + :param pipeline_id: str + The pipeline for which to get or manage permissions. + :param access_control_list: List[:class:`PipelineAccessControlRequest`] (optional) + + :returns: :class:`PipelinePermissions` + + .. py:method:: start_update(pipeline_id [, cause, full_refresh, full_refresh_selection, refresh_selection]) Queue a pipeline update. @@ -417,4 +454,17 @@ Pipelines Which pipeline trigger to use. Deprecated: Use `continuous` instead. + + + .. py:method:: update_pipeline_permissions(pipeline_id [, access_control_list]) + + Update pipeline permissions. + + Updates the permissions on a pipeline. Pipelines can inherit permissions from their root object. + + :param pipeline_id: str + The pipeline for which to get or manage permissions. + :param access_control_list: List[:class:`PipelineAccessControlRequest`] (optional) + + :returns: :class:`PipelinePermissions` \ No newline at end of file diff --git a/docs/workspace/repos.rst b/docs/workspace/repos.rst index fa20be14..e4d36eb9 100644 --- a/docs/workspace/repos.rst +++ b/docs/workspace/repos.rst @@ -94,6 +94,30 @@ Repos :returns: :class:`RepoInfo` + .. py:method:: get_repo_permission_levels(repo_id) + + Get repo permission levels. + + Gets the permission levels that a user can have on an object. + + :param repo_id: str + The repo for which to get or manage permissions. + + :returns: :class:`GetRepoPermissionLevelsResponse` + + + .. py:method:: get_repo_permissions(repo_id) + + Get repo permissions. + + Gets the permissions of a repo. Repos can inherit permissions from their root object. + + :param repo_id: str + The repo for which to get or manage permissions. + + :returns: :class:`RepoPermissions` + + .. py:method:: list( [, next_page_token, path_prefix]) Usage: @@ -121,6 +145,19 @@ Repos :returns: Iterator over :class:`RepoInfo` + .. py:method:: set_repo_permissions(repo_id [, access_control_list]) + + Set repo permissions. + + Sets permissions on a repo. Repos can inherit permissions from their root object. + + :param repo_id: str + The repo for which to get or manage permissions. + :param access_control_list: List[:class:`RepoAccessControlRequest`] (optional) + + :returns: :class:`RepoPermissions` + + .. py:method:: update(repo_id [, branch, sparse_checkout, tag]) Usage: @@ -160,4 +197,17 @@ Repos instead of the detached HEAD. + + + .. py:method:: update_repo_permissions(repo_id [, access_control_list]) + + Update repo permissions. + + Updates the permissions on a repo. Repos can inherit permissions from their root object. + + :param repo_id: str + The repo for which to get or manage permissions. + :param access_control_list: List[:class:`RepoAccessControlRequest`] (optional) + + :returns: :class:`RepoPermissions` \ No newline at end of file diff --git a/docs/workspace/serving_endpoints.rst b/docs/workspace/serving_endpoints.rst index 699d6be7..47e5ea8a 100644 --- a/docs/workspace/serving_endpoints.rst +++ b/docs/workspace/serving_endpoints.rst @@ -77,6 +77,31 @@ Serving endpoints :returns: :class:`ServingEndpointDetailed` + .. py:method:: get_serving_endpoint_permission_levels(serving_endpoint_id) + + Get serving endpoint permission levels. + + Gets the permission levels that a user can have on an object. + + :param serving_endpoint_id: str + The serving endpoint for which to get or manage permissions. + + :returns: :class:`GetServingEndpointPermissionLevelsResponse` + + + .. py:method:: get_serving_endpoint_permissions(serving_endpoint_id) + + Get serving endpoint permissions. + + Gets the permissions of a serving endpoint. Serving endpoints can inherit permissions from their root + object. + + :param serving_endpoint_id: str + The serving endpoint for which to get or manage permissions. + + :returns: :class:`ServingEndpointPermissions` + + .. py:method:: list() Retrieve all serving endpoints. @@ -108,6 +133,20 @@ Serving endpoints :returns: :class:`QueryEndpointResponse` + .. py:method:: set_serving_endpoint_permissions(serving_endpoint_id [, access_control_list]) + + Set serving endpoint permissions. + + Sets permissions on a serving endpoint. Serving endpoints can inherit permissions from their root + object. + + :param serving_endpoint_id: str + The serving endpoint for which to get or manage permissions. + :param access_control_list: List[:class:`ServingEndpointAccessControlRequest`] (optional) + + :returns: :class:`ServingEndpointPermissions` + + .. py:method:: update_config(served_models, name [, traffic_config]) Update a serving endpoint with a new config. @@ -127,4 +166,18 @@ Serving endpoints :returns: Long-running operation waiter for :class:`ServingEndpointDetailed`. See :method:wait_get_serving_endpoint_not_updating for more details. + + + .. py:method:: update_serving_endpoint_permissions(serving_endpoint_id [, access_control_list]) + + Update serving endpoint permissions. + + Updates the permissions on a serving endpoint. Serving endpoints can inherit permissions from their + root object. + + :param serving_endpoint_id: str + The serving endpoint for which to get or manage permissions. + :param access_control_list: List[:class:`ServingEndpointAccessControlRequest`] (optional) + + :returns: :class:`ServingEndpointPermissions` \ No newline at end of file diff --git a/docs/workspace/token_management.rst b/docs/workspace/token_management.rst index 857874cd..5469bc40 100644 --- a/docs/workspace/token_management.rst +++ b/docs/workspace/token_management.rst @@ -91,6 +91,24 @@ Token management :returns: :class:`TokenInfo` + .. py:method:: get_token_permission_levels() + + Get token permission levels. + + Gets the permission levels that a user can have on an object. + + :returns: :class:`GetTokenPermissionLevelsResponse` + + + .. py:method:: get_token_permissions() + + Get token permissions. + + Gets the permissions of all tokens. Tokens can inherit permissions from their root object. + + :returns: :class:`TokenPermissions` + + .. py:method:: list( [, created_by_id, created_by_username]) Usage: @@ -114,4 +132,26 @@ Token management Username of the user that created the token. :returns: Iterator over :class:`TokenInfo` + + + .. py:method:: set_token_permissions( [, access_control_list]) + + Set token permissions. + + Sets permissions on all tokens. Tokens can inherit permissions from their root object. + + :param access_control_list: List[:class:`TokenAccessControlRequest`] (optional) + + :returns: :class:`TokenPermissions` + + + .. py:method:: update_token_permissions( [, access_control_list]) + + Update token permissions. + + Updates the permissions on all tokens. Tokens can inherit permissions from their root object. + + :param access_control_list: List[:class:`TokenAccessControlRequest`] (optional) + + :returns: :class:`TokenPermissions` \ No newline at end of file diff --git a/docs/workspace/users.rst b/docs/workspace/users.rst index 68e81183..bc6fbb92 100644 --- a/docs/workspace/users.rst +++ b/docs/workspace/users.rst @@ -109,6 +109,24 @@ Users :returns: :class:`User` + .. py:method:: get_password_permission_levels() + + Get password permission levels. + + Gets the permission levels that a user can have on an object. + + :returns: :class:`GetPasswordPermissionLevelsResponse` + + + .. py:method:: get_password_permissions() + + Get password permissions. + + Gets the permissions of all passwords. Passwords can inherit permissions from their root object. + + :returns: :class:`PasswordPermissions` + + .. py:method:: list( [, attributes, count, excluded_attributes, filter, sort_by, sort_order, start_index]) Usage: @@ -190,6 +208,17 @@ Users + .. py:method:: set_password_permissions( [, access_control_list]) + + Set password permissions. + + Sets permissions on all passwords. Passwords can inherit permissions from their root object. + + :param access_control_list: List[:class:`PasswordAccessControlRequest`] (optional) + + :returns: :class:`PasswordPermissions` + + .. py:method:: update(id [, active, display_name, emails, entitlements, external_id, groups, name, roles, user_name]) Replace a user. @@ -213,4 +242,15 @@ Users Email address of the Databricks user. + + + .. py:method:: update_password_permissions( [, access_control_list]) + + Update password permissions. + + Updates the permissions on all passwords. Passwords can inherit permissions from their root object. + + :param access_control_list: List[:class:`PasswordAccessControlRequest`] (optional) + + :returns: :class:`PasswordPermissions` \ No newline at end of file diff --git a/docs/workspace/warehouses.rst b/docs/workspace/warehouses.rst index a843a10c..510de4f6 100644 --- a/docs/workspace/warehouses.rst +++ b/docs/workspace/warehouses.rst @@ -225,6 +225,31 @@ SQL Warehouses :returns: :class:`GetWarehouseResponse` + .. py:method:: get_warehouse_permission_levels(warehouse_id) + + Get SQL warehouse permission levels. + + Gets the permission levels that a user can have on an object. + + :param warehouse_id: str + The SQL warehouse for which to get or manage permissions. + + :returns: :class:`GetWarehousePermissionLevelsResponse` + + + .. py:method:: get_warehouse_permissions(warehouse_id) + + Get SQL warehouse permissions. + + Gets the permissions of a SQL warehouse. SQL warehouses can inherit permissions from their root + object. + + :param warehouse_id: str + The SQL warehouse for which to get or manage permissions. + + :returns: :class:`WarehousePermissions` + + .. py:method:: get_workspace_warehouse_config() Get the workspace configuration. @@ -258,6 +283,19 @@ SQL Warehouses :returns: Iterator over :class:`EndpointInfo` + .. py:method:: set_warehouse_permissions(warehouse_id [, access_control_list]) + + Set SQL warehouse permissions. + + Sets permissions on a SQL warehouse. SQL warehouses can inherit permissions from their root object. + + :param warehouse_id: str + The SQL warehouse for which to get or manage permissions. + :param access_control_list: List[:class:`WarehouseAccessControlRequest`] (optional) + + :returns: :class:`WarehousePermissions` + + .. py:method:: set_workspace_warehouse_config( [, channel, config_param, data_access_config, enabled_warehouse_types, global_param, google_service_account, instance_profile_arn, security_policy, sql_configuration_parameters]) Set the workspace configuration. @@ -316,4 +354,18 @@ SQL Warehouses :returns: Long-running operation waiter for :class:`GetWarehouseResponse`. See :method:wait_get_warehouse_stopped for more details. + + + .. py:method:: update_warehouse_permissions(warehouse_id [, access_control_list]) + + Update SQL warehouse permissions. + + Updates the permissions on a SQL warehouse. SQL warehouses can inherit permissions from their root + object. + + :param warehouse_id: str + The SQL warehouse for which to get or manage permissions. + :param access_control_list: List[:class:`WarehouseAccessControlRequest`] (optional) + + :returns: :class:`WarehousePermissions` \ No newline at end of file diff --git a/docs/workspace/workspace.rst b/docs/workspace/workspace.rst index 62447ff1..a974b5bf 100644 --- a/docs/workspace/workspace.rst +++ b/docs/workspace/workspace.rst @@ -131,6 +131,35 @@ Workspace :returns: :class:`ObjectInfo` + .. py:method:: get_workspace_object_permission_levels(workspace_object_type, workspace_object_id) + + Get workspace object permission levels. + + Gets the permission levels that a user can have on an object. + + :param workspace_object_type: str + The workspace object type for which to get or manage permissions. + :param workspace_object_id: str + The workspace object for which to get or manage permissions. + + :returns: :class:`GetWorkspaceObjectPermissionLevelsResponse` + + + .. py:method:: get_workspace_object_permissions(workspace_object_type, workspace_object_id) + + Get workspace object permissions. + + Gets the permissions of a workspace object. Workspace objects can inherit permissions from their + parent objects or root object. + + :param workspace_object_type: str + The workspace object type for which to get or manage permissions. + :param workspace_object_id: str + The workspace object for which to get or manage permissions. + + :returns: :class:`WorkspaceObjectPermissions` + + .. py:method:: import_(path [, content, format, language, overwrite]) Usage: @@ -228,6 +257,38 @@ Workspace + .. py:method:: set_workspace_object_permissions(workspace_object_type, workspace_object_id [, access_control_list]) + + Set workspace object permissions. + + Sets permissions on a workspace object. Workspace objects can inherit permissions from their parent + objects or root object. + + :param workspace_object_type: str + The workspace object type for which to get or manage permissions. + :param workspace_object_id: str + The workspace object for which to get or manage permissions. + :param access_control_list: List[:class:`WorkspaceObjectAccessControlRequest`] (optional) + + :returns: :class:`WorkspaceObjectPermissions` + + + .. py:method:: update_workspace_object_permissions(workspace_object_type, workspace_object_id [, access_control_list]) + + Update workspace object permissions. + + Updates the permissions on a workspace object. Workspace objects can inherit permissions from their + parent objects or root object. + + :param workspace_object_type: str + The workspace object type for which to get or manage permissions. + :param workspace_object_id: str + The workspace object for which to get or manage permissions. + :param access_control_list: List[:class:`WorkspaceObjectAccessControlRequest`] (optional) + + :returns: :class:`WorkspaceObjectPermissions` + + .. py:method:: upload(path, content [, format, language, overwrite]) Usage: