2121# See the License for the specific language governing permissions and
2222# limitations under the License.
2323
24+ import functools
25+
2426import click
2527
2628from databricks_cli .click_types import JsonClickType
3335
3436############# Storage Credential Commands ############
3537
38+ def fill_credential (
39+ data , aws_iam_role_arn , az_sp_directory_id , az_sp_application_id ,
40+ az_sp_client_secret , az_mi_access_connector_id , az_mi_id , gcp_sak_email ,
41+ gcp_sak_private_key_id , gcp_sak_private_key ):
42+ if aws_iam_role_arn is not None :
43+ data ['aws_iam_role' ] = {
44+ 'role_arn' : aws_iam_role_arn
45+ }
46+
47+ if ((az_sp_directory_id is not None ) or (az_sp_application_id is not None ) or
48+ (az_sp_client_secret is not None )):
49+ data ['azure_service_principal' ] = {
50+ 'directory_id' : az_sp_directory_id ,
51+ 'application_id' : az_sp_application_id ,
52+ 'client_secret' : az_sp_client_secret
53+ }
54+
55+ if (az_mi_access_connector_id is not None ) or (az_mi_id is not None ):
56+ data ['azure_managed_identity' ] = {
57+ 'access_connector_id' : az_mi_access_connector_id ,
58+ 'managed_identity_id' : az_mi_id
59+ }
60+
61+ if ((gcp_sak_email is not None ) or (gcp_sak_private_key_id is not None ) or
62+ (gcp_sak_private_key is not None )):
63+ data ['gcp_service_account_key' ] = {
64+ 'email' : gcp_sak_email ,
65+ 'private_key_id' : gcp_sak_private_key_id ,
66+ 'private_key' : gcp_sak_private_key
67+ }
68+
69+
70+ def create_update_common_options (f ):
71+ @click .option ('--aws-iam-role-arn' , default = None ,
72+ help = 'The Amazon Resource Name (ARN) of the AWS IAM role for S3 data access.' )
73+ @click .option ('--az-sp-directory-id' , default = None ,
74+ help = (
75+ 'The directory ID corresponding to the Azure Active Directory (AAD) '
76+ 'tenant of the application.' ))
77+ @click .option ('--az-sp-application-id' , default = None ,
78+ help = (
79+ 'The application ID of the application registration within the referenced '
80+ 'AAD tenant.' ))
81+ @click .option ('--az-sp-client-secret' , default = None ,
82+ help = 'The client secret generated for the above app ID in AAD.' )
83+ @click .option ('--az-mi-access-connector-id' , default = None ,
84+ help = (
85+ 'The Azure resource ID of the Azure Databricks Access Connector. '
86+ 'Use the format, '
87+ '/subscriptions/{guid}/resourceGroups/{rg-name}/providers/Microsoft.Databricks'
88+ '/accessConnectors/{connector-name} .' ))
89+ @click .option ('--az-mi-id' , default = None ,
90+ help = (
91+ 'The Azure resource ID of the managed identity. Use the format, '
92+ '/subscriptions/{guid}/resourceGroups/{rg-name}/providers'
93+ '/Microsoft.ManagedIdentity/userAssignedIdentities/{identity-name} .'
94+ 'This is only available for user-assigned identities. '
95+ 'For system-assigned identities, access-connector-id is used to identify '
96+ 'the identity. If this flag is not provided, '
97+ 'then we assume that it is using the system-assigned identity.' ))
98+ @click .option ('--gcp-sak-email' , default = None ,
99+ help = (
100+ 'Credential for GCP Service Account Key. '
101+ 'The email of the service account.' ))
102+ @click .option ('--gcp-sak-private-key-id' , default = None ,
103+ help = (
104+ 'Credential for GCP Service Account Key. '
105+ 'The ID of the service account\' s private key.' ))
106+ @click .option ('--gcp-sak-private-key' , default = None ,
107+ help = (
108+ 'Credential for GCP Service Account Key. '
109+ 'The service account\' s RSA private key.' ))
110+ @click .option ('--comment' , default = None ,
111+ help = 'Free-form text description.' )
112+ @functools .wraps (f )
113+ def wrapper (* args , ** kwargs ):
114+ f (* args , ** kwargs )
115+ return wrapper
116+
36117
37118@click .command (context_settings = CONTEXT_SETTINGS ,
38119 short_help = 'Create storage credential.' )
120+ @click .option ('--name' , default = None ,
121+ help = 'Name of new storage credential' )
122+ @create_update_common_options
39123@click .option ('--skip-validation' , '-s' , 'skip_val' , is_flag = True , default = False ,
40124 help = 'Skip the validation of new credential info before creation' )
41125@click .option ('--json-file' , default = None , type = click .Path (),
50134# Until that is fixed (should return a 400), show full error trace.
51135#@eat_exceptions
52136@provide_api_client
53- def create_credential_cli (api_client , skip_val , json_file , json ):
137+ def create_credential_cli (api_client , name , aws_iam_role_arn ,
138+ az_sp_directory_id , az_sp_application_id , az_sp_client_secret ,
139+ az_mi_access_connector_id , az_mi_id , gcp_sak_email ,
140+ gcp_sak_private_key_id , gcp_sak_private_key , comment ,
141+ skip_val , json_file , json ):
54142 """
55143 Create new storage credential.
56144
57145 The public specification for the JSON request is in development.
58146 """
59- json_cli_base (json_file , json ,
60- lambda json : UnityCatalogApi (api_client ).create_storage_credential (json ,
61- skip_val ),
62- encode_utf8 = True )
147+ has_credential_flag = (
148+ (aws_iam_role_arn is not None ) or
149+ (az_sp_directory_id is not None ) or (az_sp_application_id is not None ) or
150+ (az_sp_client_secret is not None ) or (az_mi_access_connector_id is not None ) or
151+ (az_mi_id is not None ) or (gcp_sak_email is not None ) or
152+ (gcp_sak_private_key_id is not None ) or (gcp_sak_private_key is not None ))
153+ if ((name is not None ) or has_credential_flag or (comment is not None )):
154+ if (json_file is not None ) or (json is not None ):
155+ raise ValueError ('Cannot specify JSON if any other creation flags are specified' )
156+ data = {
157+ 'name' : name ,
158+ 'comment' : comment
159+ }
160+
161+ fill_credential (
162+ data , aws_iam_role_arn , az_sp_directory_id , az_sp_application_id ,
163+ az_sp_client_secret , az_mi_access_connector_id , az_mi_id , gcp_sak_email ,
164+ gcp_sak_private_key_id , gcp_sak_private_key )
165+
166+ cred_json = UnityCatalogApi (api_client ).create_storage_credential (data , skip_val )
167+ click .echo (mc_pretty_format (cred_json ))
168+ else :
169+ json_cli_base (json_file , json ,
170+ lambda json : UnityCatalogApi (api_client ).create_storage_credential (json ,
171+ skip_val ),
172+ encode_utf8 = True )
63173
64174
65175@click .command (context_settings = CONTEXT_SETTINGS ,
@@ -98,6 +208,10 @@ def get_credential_cli(api_client, name):
98208 short_help = 'Update a storage credential.' )
99209@click .option ('--name' , required = True ,
100210 help = 'Name of the storage credential to update.' )
211+ @click .option ('--new-name' , default = None , help = 'New name of the storage credential.' )
212+ @create_update_common_options
213+ @click .option ('--owner' , default = None ,
214+ help = 'Owner of the storage credential.' )
101215@click .option ('--skip-validation' , '-s' , 'skip_val' , is_flag = True , default = False ,
102216 help = 'Skip the validation of new credential info before update' )
103217@click .option ('--json-file' , default = None , type = click .Path (),
@@ -109,17 +223,45 @@ def get_credential_cli(api_client, name):
109223# See comment for create-storage-credential
110224#@eat_exceptions
111225@provide_api_client
112- def update_credential_cli (api_client , name , skip_val , json_file , json ):
226+ def update_credential_cli (api_client , name , new_name , aws_iam_role_arn ,
227+ az_sp_directory_id , az_sp_application_id , az_sp_client_secret ,
228+ az_mi_access_connector_id , az_mi_id , gcp_sak_email ,
229+ gcp_sak_private_key_id , gcp_sak_private_key , comment , owner ,
230+ skip_val , json_file , json ):
113231 """
114232 Update a storage credential.
115233
116234 The public specification for the JSON request is in development.
117235 """
118- json_cli_base (json_file , json ,
119- lambda json : UnityCatalogApi (api_client ).update_storage_credential (name ,
120- json ,
121- skip_val ),
122- encode_utf8 = True )
236+ has_credential_flag = (
237+ (aws_iam_role_arn is not None ) or
238+ (az_sp_directory_id is not None ) or (az_sp_application_id is not None ) or
239+ (az_sp_client_secret is not None ) or (az_mi_access_connector_id is not None ) or
240+ (az_mi_id is not None ) or (gcp_sak_email is not None ) or
241+ (gcp_sak_private_key_id is not None ) or (gcp_sak_private_key is not None ))
242+ if ((new_name is not None ) or has_credential_flag or
243+ (comment is not None ) or (owner is not None )):
244+ if (json_file is not None ) or (json is not None ):
245+ raise ValueError ('Cannot specify JSON if any other update flags are specified' )
246+ data = {
247+ 'name' : new_name ,
248+ 'comment' : comment ,
249+ 'owner' : owner
250+ }
251+
252+ fill_credential (
253+ data , aws_iam_role_arn , az_sp_directory_id , az_sp_application_id ,
254+ az_sp_client_secret , az_mi_access_connector_id , az_mi_id , gcp_sak_email ,
255+ gcp_sak_private_key_id , gcp_sak_private_key )
256+
257+ cred_json = UnityCatalogApi (api_client ).update_storage_credential (name , data , skip_val )
258+ click .echo (mc_pretty_format (cred_json ))
259+ else :
260+ json_cli_base (json_file , json ,
261+ lambda json : UnityCatalogApi (api_client ).update_storage_credential (name ,
262+ json ,
263+ skip_val ),
264+ encode_utf8 = True )
123265
124266
125267@click .command (context_settings = CONTEXT_SETTINGS ,
0 commit comments