Skip to content

Commit ecf19d1

Browse files
[HDInsight] Update hdinsight api-version to 2025-01-15-preview (#32273)
Co-authored-by: Yukun Li (Beyondsoft) <[email protected]>
1 parent 1fab005 commit ecf19d1

File tree

38 files changed

+47840
-10912
lines changed

38 files changed

+47840
-10912
lines changed

src/azure-cli/azure/cli/command_modules/hdinsight/_help.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,48 @@
156156
az hdinsight create -t spark --version 3.6 -g MyResourceGroup -n MyCluster \\
157157
-p "HttpPassword1234!" --storage-account MyStorageAccount \\
158158
--enable-compute-isolation --workernode-size "Standard_E8S_V3" --headnode-size "Standard_E8S_V3"
159+
- name: Create a cluster with WASB + MSI.
160+
text: |-
161+
az hdinsight create -t spark -g MyResourceGroup -n MyCluster \\
162+
-p "HttpPassword1234!" \\
163+
--storage-account MyStorageAccount \\
164+
--storage-account-managed-identity MyMSI
165+
- name: Create a entra user cluster with Entra User By objectId or upn (comma-separated)
166+
text: |-
167+
az hdinsight create -t spark -g MyResourceGroup -n MyCluster \\
168+
--ssh-password "sshPassword1234!" \\
169+
--storage-account MyStorageAccount \\
170+
--entra-user-identity "00000000-0000-0000-0000-000000000000","00000000-0000-0000-0000-000000000000","[email protected]"
171+
- name: Create a entra user cluster with Entra User By objectId or upn (comma-separated, use short name)
172+
text: |-
173+
az hdinsight create -t spark -g MyResourceGroup -n MyCluster \\
174+
--ssh-password "sshPassword1234!" \\
175+
--storage-account MyStorageAccount \\
176+
--entra-uid "00000000-0000-0000-0000-000000000000","00000000-0000-0000-0000-000000000000","[email protected]"
177+
- name: Create a entra user cluster with Entra User By objectId or upn (space-separated)
178+
text: |-
179+
az hdinsight create -t spark -g MyResourceGroup -n MyCluster \\
180+
--ssh-password "sshPassword1234!" \\
181+
--storage-account MyStorageAccount \\
182+
--entra-user-identity "00000000-0000-0000-0000-000000000000" "00000000-0000-0000-0000-000000000000" "[email protected]"
183+
- name: Create a entra user cluster with Entra User By a JSON string
184+
text: |-
185+
az hdinsight create -t spark -g MyResourceGroup -n MyCluster \\
186+
--ssh-password "sshPassword1234!" \\
187+
--storage-account MyStorageAccount \\
188+
--entra-user-full-info '[{\"objectId\": \"00000000-0000-0000-0000-000000000000\",\"displayName\": \"name\",\"upn\": \"[email protected]\"}]'
189+
- name: Create a entra user cluster with Entra User By a JSON string (use short name)
190+
text: |-
191+
az hdinsight create -t spark -g MyResourceGroup -n MyCluster \\
192+
--ssh-password "sshPassword1234!" \\
193+
--storage-account MyStorageAccount \\
194+
--entra-uinfo '[{\"objectId\": \"00000000-0000-0000-0000-000000000000\",\"displayName\": \"name\",\"upn\": \"[email protected]\"}]'
195+
- name: Create a entra user cluster with Entra User By a JSON file
196+
text: |-
197+
az hdinsight create -t spark -g MyResourceGroup -n MyCluster \\
198+
--ssh-password "sshPassword1234!" \\
199+
--storage-account MyStorageAccount \\
200+
--entra-user-full-info @config.json
159201
"""
160202

161203
helps['hdinsight resize'] = """
@@ -434,3 +476,52 @@
434476
type: command
435477
short-summary: Place the CLI in a waiting state until an operation is complete.
436478
"""
479+
480+
helps['hdinsight credentials'] = """
481+
type: group
482+
short-summary: Manage credentials for an existing HDInsight cluster, including Entra ID users and HTTP password.
483+
"""
484+
485+
helps['hdinsight credentials update'] = """
486+
type: command
487+
short-summary: Update credentials for an existing HDInsight cluster, including Entra ID users and HTTP password.
488+
examples:
489+
- name: Update Entra ID users by objectId or upn (comma-separated)
490+
text: |-
491+
az hdinsight credentials update --name MyCluster --resource-group rg \\
492+
--entra-user-identity "00000000-0000-0000-0000-000000000000","00000000-0000-0000-0000-000000000000","[email protected]"
493+
- name: Update Entra ID users by objectId or upn (comma-separated, use short name)
494+
text: |-
495+
az hdinsight credentials update --name MyCluster --resource-group rg \\
496+
--entra-uid "00000000-0000-0000-0000-000000000000","00000000-0000-0000-0000-000000000000","[email protected]"
497+
- name: Update Entra ID users by objectId or upn (space-separated)
498+
text: |-
499+
az hdinsight credentials update --name MyCluster --resource-group rg \\
500+
--entra-user-identity "00000000-0000-0000-0000-000000000000","00000000-0000-0000-0000-000000000000","[email protected]"
501+
- name: Update Entra ID users using a JSON string
502+
text: |-
503+
az hdinsight credentials update --name MyCluster --resource-group rg \\
504+
--entra-user-full-info '[{\"objectId\": \"00000000-0000-0000-0000-000000000000\",\"displayName\": \"name\",\"upn\": \"[email protected]\"}]'
505+
- name: Update Entra ID users using a JSON string (use short name)
506+
text: |-
507+
az hdinsight credentials update --name MyCluster --resource-group rg \\
508+
--entra-uinfo '[{\"objectId\": \"00000000-0000-0000-0000-000000000000\",\"displayName\": \"name\",\"upn\": \"[email protected]\"}]'
509+
- name: Update Entra ID users using a JSON file
510+
text: |-
511+
az hdinsight credentials update --name MyCluster --resource-group rg \\
512+
--entra-user-full-info @config.json
513+
- name: Update the HTTP password for the cluster
514+
text: |-
515+
az hdinsight credentials update --name MyCluster --resource-group rg \\
516+
--http-password "HttpPassword1234!"
517+
"""
518+
519+
helps['hdinsight credentials show'] = """
520+
type: command
521+
short-summary: Show credential configuration of an existing HDInsight cluster, including HTTP username, password, and Entra ID user settings
522+
"""
523+
524+
helps['hdinsight credentials wait'] = """
525+
type: command
526+
short-summary: Place the CLI in a waiting state until an operation is complete.
527+
"""

src/azure-cli/azure/cli/command_modules/hdinsight/_params.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,17 @@ def load_arguments(self, _):
8484
help='HTTP username for the cluster. Default: admin.')
8585
c.argument('http_password', options_list=['--http-password', '-p'], arg_group='HTTP',
8686
help='HTTP password for the cluster. Will prompt if not given.')
87+
c.argument('entra_user_identity', options_list=['--entra-user-identity', '--entra-uid'],
88+
arg_group='HTTP', nargs='+',
89+
help='One or more Entra user identities (object ID or user principal name) '
90+
'to associate with the cluster. Multiple values can be separated by spaces or commas.')
91+
c.argument('entra_user_full_info', options_list=['--entra-user-full-info', '--entra-uinfo'],
92+
arg_group='HTTP', completer=FilesCompleter(), type=shell_safe_json_parse,
93+
help='The Entra user information to associate with the cluster. '
94+
'This can be provided as a JSON string or from a file using the `@{path}` syntax. '
95+
'Each entry should include "objectId", "upn", and "displayName" fields. '
96+
'Please see: `https://github.com/Azure/azure-cli/blob/dev/src/azure-cli/azure/cli/'
97+
'command_modules/hdinsight/tests/latest/entrauserconfig.json`')
8798

8899
# SSH
89100
c.argument('ssh_username', options_list=['--ssh-user', '-U'], arg_group='SSH',
@@ -411,3 +422,21 @@ def load_arguments(self, _):
411422
with self.argument_context('hdinsight autoscale condition delete') as c:
412423
c.argument('index', nargs='+', type=int,
413424
help='The Space-separated list of condition indices which starts with 0 to delete.')
425+
426+
# credentials
427+
with self.argument_context('hdinsight credentials update') as c:
428+
c.argument('http_username', options_list=['--http-user', '-u'], arg_group='HTTP',
429+
help='HTTP username for the cluster. Default: admin.')
430+
c.argument('http_password', options_list=['--http-password', '-p'], arg_group='HTTP',
431+
help='HTTP password for the cluster. Will prompt if not given.')
432+
c.argument('entra_user_identity', options_list=['--entra-user-identity', '--entra-uid'],
433+
arg_group='HTTP', nargs='+',
434+
help='One or more Entra user identities (object ID or user principal name) to '
435+
'associate with the cluster. Multiple values can be separated by spaces or commas.')
436+
c.argument('entra_user_full_info', options_list=['--entra-user-full-info', '--entra-uinfo'],
437+
arg_group='HTTP', completer=FilesCompleter(), type=shell_safe_json_parse,
438+
help='The Entra user information to associate with the cluster. '
439+
'This can be provided as a JSON string or from a file using the `@{path}` syntax. '
440+
'Each entry should include "objectId", "upn", and "displayName" fields. '
441+
'Please see: `https://github.com/Azure/azure-cli/blob/dev/src/azure-cli/azure/cli/'
442+
'command_modules/hdinsight/tests/latest/entrauserconfig.json`')

src/azure-cli/azure/cli/command_modules/hdinsight/commands.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,9 @@ def load_command_table(self, _): # pylint: disable=too-many-statements
135135
g.custom_command('list', 'list_autoscale_condition')
136136
g.custom_command('delete', 'delete_autoscale_condition', supports_no_wait=True, confirmation=True)
137137
g.wait_command('wait')
138+
139+
# credentials operations
140+
with self.command_group('hdinsight credentials', hdinsight_clusters_sdk, client_factory=cf_hdinsight_clusters) as g:
141+
g.show_command('show', 'get_gateway_settings')
142+
g.custom_command('update', 'update_gateway_settings', supports_no_wait=True, confirmation=True)
143+
g.wait_command('wait')

src/azure-cli/azure/cli/command_modules/hdinsight/custom.py

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from knack.prompting import prompt_pass, NoTTYException
77
from knack.util import CLIError
88
from azure.cli.core.util import sdk_no_wait, user_confirmation
9-
from azure.cli.core.azclierror import RequiredArgumentMissingError
9+
from azure.cli.core.azclierror import RequiredArgumentMissingError, MutuallyExclusiveArgumentError
1010

1111
logger = get_logger(__name__)
1212

@@ -20,7 +20,7 @@ def create_cluster(cmd, client, cluster_name, resource_group_name, cluster_type,
2020
kafka_client_group_id=None, kafka_client_group_name=None,
2121
workernode_count=3, workernode_data_disks_per_node=None,
2222
workernode_data_disk_storage_account_type=None, workernode_data_disk_size=None,
23-
http_username=None, http_password=None,
23+
http_username=None, http_password=None, entra_user_identity=None, entra_user_full_info=None,
2424
ssh_username='sshuser', ssh_password=None, ssh_public_key=None,
2525
storage_account=None, storage_account_key=None,
2626
storage_default_container=None, storage_default_filesystem=None,
@@ -41,7 +41,8 @@ def create_cluster(cmd, client, cluster_name, resource_group_name, cluster_type,
4141
enable_compute_isolation=None, host_sku=None, zones=None, private_link_configurations=None,
4242
no_validation_timeout=False, outbound_dependencies_managed_type=None):
4343
from .util import build_identities_info, build_virtual_network_profile, parse_domain_name, \
44-
get_storage_account_endpoint, validate_esp_cluster_create_params, set_vm_size
44+
get_storage_account_endpoint, validate_esp_cluster_create_params, set_vm_size, \
45+
is_wasb_storage_account, get_entra_user_info
4546
from azure.mgmt.hdinsight.models import ClusterCreateParametersExtended, ClusterCreateProperties, OSType, \
4647
ClusterDefinition, ComputeProfile, HardwareProfile, Role, OsProfile, LinuxOperatingSystemProfile, \
4748
StorageProfile, StorageAccount, DataDisksGroups, SecurityProfile, \
@@ -84,17 +85,25 @@ def create_cluster(cmd, client, cluster_name, resource_group_name, cluster_type,
8485
if not http_username:
8586
http_username = 'admin' # Implement default logic here, in case a user specifies the username in configurations
8687

87-
if not http_password:
88+
if not http_password and not entra_user_identity and not entra_user_full_info:
8889
try:
8990
http_password = prompt_pass('HTTP password for the cluster:', confirm=True)
9091
except NoTTYException:
9192
raise CLIError('Please specify --http-password in non-interactive mode.')
9293

9394
# Update the cluster config with the HTTP credentials
94-
gateway_config['restAuthCredential.isEnabled'] = 'true' # HTTP credentials are required
95-
http_username = http_username or gateway_config['restAuthCredential.username']
96-
gateway_config['restAuthCredential.username'] = http_username
97-
gateway_config['restAuthCredential.password'] = http_password
95+
if not entra_user_identity and not entra_user_full_info:
96+
gateway_config['restAuthCredential.isEnabled'] = 'true' # HTTP credentials are required
97+
http_username = http_username or gateway_config['restAuthCredential.username']
98+
gateway_config['restAuthCredential.username'] = http_username
99+
gateway_config['restAuthCredential.password'] = http_password
100+
else:
101+
if entra_user_identity and entra_user_full_info:
102+
raise MutuallyExclusiveArgumentError(
103+
'Cannot provide both --entra-user-identity and'
104+
' --entra-user-full-info parameters.')
105+
gateway_config['restAuthCredential.isEnabled'] = 'false'
106+
gateway_config['restAuthEntraUsers'] = get_entra_user_info(cmd, entra_user_identity, entra_user_full_info)
98107
cluster_configurations['gateway'] = gateway_config
99108

100109
# Validate whether SSH credentials were provided
@@ -107,13 +116,19 @@ def create_cluster(cmd, client, cluster_name, resource_group_name, cluster_type,
107116
raise CLIError('Either the default container or the default filesystem can be specified, but not both.')
108117

109118
# Retrieve primary blob service endpoint
110-
is_wasb = not storage_account_managed_identity
119+
is_wasb = None
120+
if storage_default_container:
121+
is_wasb = True
122+
elif storage_default_filesystem:
123+
is_wasb = False
124+
else:
125+
is_wasb = is_wasb_storage_account(cmd, storage_account)
111126
storage_account_endpoint = None
112127
if storage_account:
113128
storage_account_endpoint = get_storage_account_endpoint(cmd, storage_account, is_wasb)
114129

115130
# Attempt to infer the storage account key from the endpoint
116-
if not storage_account_key and storage_account and is_wasb:
131+
if not storage_account_key and storage_account and not storage_account_managed_identity and is_wasb:
117132
from .util import get_key_for_storage_account
118133
logger.info('Storage account key not specified. Attempting to retrieve key...')
119134
key = get_key_for_storage_account(cmd, storage_account)
@@ -130,8 +145,8 @@ def create_cluster(cmd, client, cluster_name, resource_group_name, cluster_type,
130145
logger.warning('Default ADLS file system not specified, using "%s".', storage_default_filesystem)
131146

132147
# Validate storage info parameters
133-
if is_wasb and not _all_or_none(storage_account, storage_account_key, storage_default_container):
134-
raise CLIError('If storage details are specified, the storage account, storage account key, '
148+
if is_wasb and not _all_or_none(storage_account, storage_default_container):
149+
raise CLIError('If storage details are specified, the storage account, '
135150
'and the default container must be specified.')
136151
if not is_wasb and not _all_or_none(storage_account, storage_default_filesystem):
137152
raise CLIError('If storage details are specified, the storage account, '
@@ -903,3 +918,34 @@ def _extract_and_validate_autoscale_configuration(cluster):
903918
def _validate_schedule_configuration(autoscale_configuration):
904919
if not autoscale_configuration.recurrence:
905920
raise CLIError('The cluster has not enabled Schedule-based autoscale.')
921+
922+
923+
def update_gateway_settings(cmd, client, cluster_name, resource_group_name, http_username=None,
924+
http_password=None, entra_user_identity=None, entra_user_full_info=None, no_wait=False):
925+
from azure.mgmt.hdinsight.models import UpdateGatewaySettingsParameters
926+
from .util import get_entra_user_info
927+
if not http_password and not entra_user_identity and not entra_user_full_info:
928+
try:
929+
http_password = prompt_pass('HTTP password for the cluster:', confirm=True)
930+
except NoTTYException:
931+
raise CLIError('Please specify --http-password in non-interactive mode.')
932+
if http_password and not http_username:
933+
http_username = 'admin'
934+
if entra_user_identity and entra_user_full_info:
935+
raise MutuallyExclusiveArgumentError(
936+
'Cannot provide both --entra-user-identity and'
937+
' --entra-user-full-info parameters.')
938+
rest_auth_entra_users_data = None
939+
if entra_user_identity or entra_user_full_info:
940+
rest_auth_entra_users_data = get_entra_user_info(cmd, entra_user_identity, entra_user_full_info, False)
941+
update_gateway_settings_parameters = UpdateGatewaySettingsParameters(
942+
is_credential_enabled=bool(http_password),
943+
user_name=http_username,
944+
password=http_password,
945+
rest_auth_entra_users=rest_auth_entra_users_data
946+
)
947+
try:
948+
return sdk_no_wait(no_wait, client.begin_update_gateway_settings, resource_group_name,
949+
cluster_name, update_gateway_settings_parameters)
950+
except Exception as ex:
951+
raise CLIError(str(ex))
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[
2+
{
3+
"objectId": "00000000-0000-0000-0000-000000000000",
4+
"displayName": "name",
5+
6+
},
7+
{
8+
"objectId": "00000000-0000-0000-0000-000000000000",
9+
"displayName": "name",
10+
11+
}
12+
]

0 commit comments

Comments
 (0)