@@ -2219,60 +2219,23 @@ def aks_create(cmd, client, resource_group_name, name, ssh_key_value, # pylint:
2219
2219
retry_exception = Exception (None )
2220
2220
for _ in range (0 , max_retry ):
2221
2221
try :
2222
- need_pull_for_result = (monitoring or
2223
- (enable_managed_identity and attach_acr ) or
2224
- ingress_appgw_addon_enabled or
2225
- enable_virtual_node or
2226
- need_post_creation_vnet_permission_granting )
2227
- if need_pull_for_result :
2228
- # adding a wait here since we rely on the result for role assignment
2229
- result = LongRunningOperation (cmd .cli_ctx )(client .create_or_update (
2230
- resource_group_name = resource_group_name ,
2231
- resource_name = name ,
2232
- parameters = mc ))
2233
- else :
2234
- result = sdk_no_wait (no_wait ,
2235
- client .create_or_update ,
2236
- resource_group_name = resource_group_name ,
2237
- resource_name = name ,
2238
- parameters = mc ,
2239
- custom_headers = custom_headers )
2240
- if monitoring :
2241
- cloud_name = cmd .cli_ctx .cloud .name
2242
- # add cluster spn/msi Monitoring Metrics Publisher role assignment to publish metrics to MDM
2243
- # mdm metrics is supported only in azure public cloud, so add the role assignment only in this cloud
2244
- if cloud_name .lower () == 'azurecloud' :
2245
- from msrestazure .tools import resource_id
2246
- cluster_resource_id = resource_id (
2247
- subscription = subscription_id ,
2248
- resource_group = resource_group_name ,
2249
- namespace = 'Microsoft.ContainerService' , type = 'managedClusters' ,
2250
- name = name
2251
- )
2252
- _add_monitoring_role_assignment (result , cluster_resource_id , cmd )
2253
- if enable_managed_identity and attach_acr :
2254
- if result .identity_profile is None or result .identity_profile ["kubeletidentity" ] is None :
2255
- logger .warning ('Your cluster is successfully created, but we failed to attach acr to it, '
2256
- 'you can manually grant permission to the identity named <ClUSTER_NAME>-agentpool '
2257
- 'in MC_ resource group to give it permission to pull from ACR.' )
2258
- else :
2259
- kubelet_identity_client_id = result .identity_profile ["kubeletidentity" ].client_id
2260
- _ensure_aks_acr (cmd .cli_ctx ,
2261
- client_id = kubelet_identity_client_id ,
2262
- acr_name_or_id = attach_acr ,
2263
- subscription_id = subscription_id )
2264
- if ingress_appgw_addon_enabled :
2265
- _add_ingress_appgw_addon_role_assignment (result , cmd )
2266
- if enable_virtual_node :
2267
- _add_virtual_node_role_assignment (cmd , result , vnet_subnet_id )
2268
- if need_post_creation_vnet_permission_granting :
2269
- if not _create_role_assignment (cmd .cli_ctx , 'Network Contributor' ,
2270
- result .identity .principal_id , scope = vnet_subnet_id ,
2271
- resolve_assignee = False ):
2272
- logger .warning ('Could not create a role assignment for subnet. '
2273
- 'Are you an Owner on this subscription?' )
2274
-
2275
- return result
2222
+ created_cluster = _put_managed_cluster_ensuring_permission (
2223
+ cmd ,
2224
+ client ,
2225
+ subscription_id ,
2226
+ resource_group_name ,
2227
+ name ,
2228
+ mc ,
2229
+ monitoring ,
2230
+ ingress_appgw_addon_enabled ,
2231
+ enable_virtual_node ,
2232
+ need_post_creation_vnet_permission_granting ,
2233
+ vnet_subnet_id ,
2234
+ enable_managed_identity ,
2235
+ attach_acr ,
2236
+ custom_headers ,
2237
+ no_wait )
2238
+ return created_cluster
2276
2239
except CloudError as ex :
2277
2240
retry_exception = ex
2278
2241
if 'not found in Active Directory tenant' in ex .message :
@@ -2486,6 +2449,9 @@ def aks_update(cmd, client, resource_group_name, name,
2486
2449
enable_ahub = False ,
2487
2450
disable_ahub = False ,
2488
2451
windows_admin_password = None ,
2452
+ enable_managed_identity = False ,
2453
+ assign_identity = None ,
2454
+ yes = False ,
2489
2455
no_wait = False ):
2490
2456
update_autoscaler = enable_cluster_autoscaler + disable_cluster_autoscaler + update_cluster_autoscaler
2491
2457
update_lb_profile = is_load_balancer_profile_provided (load_balancer_managed_outbound_ip_count ,
@@ -2506,7 +2472,9 @@ def aks_update(cmd, client, resource_group_name, name,
2506
2472
not update_aad_profile and
2507
2473
not enable_ahub and
2508
2474
not disable_ahub and
2509
- not windows_admin_password ):
2475
+ not windows_admin_password and
2476
+ not enable_managed_identity and
2477
+ not assign_identity ):
2510
2478
raise CLIError ('Please specify one or more of "--enable-cluster-autoscaler" or '
2511
2479
'"--disable-cluster-autoscaler" or '
2512
2480
'"--update-cluster-autoscaler" or '
@@ -2525,7 +2493,12 @@ def aks_update(cmd, client, resource_group_name, name,
2525
2493
'"--aad-admin-group-object-ids" or '
2526
2494
'"--enable-ahub" or '
2527
2495
'"--disable-ahub" or '
2528
- '"--windows-admin-password"' )
2496
+ '"--windows-admin-password" or '
2497
+ '"--enable-managed-identity" or '
2498
+ '"--assign-identity"' )
2499
+
2500
+ if not enable_managed_identity and assign_identity :
2501
+ raise CLIError ('--assign-identity can only be specified when --enable-managed-identity is specified' )
2529
2502
2530
2503
instance = client .get (resource_group_name , name )
2531
2504
# For multi-agent pool, use the az aks nodepool command
@@ -2655,7 +2628,72 @@ def aks_update(cmd, client, resource_group_name, name,
2655
2628
if windows_admin_password :
2656
2629
instance .windows_profile .admin_password = windows_admin_password
2657
2630
2658
- return sdk_no_wait (no_wait , client .create_or_update , resource_group_name , name , instance )
2631
+ current_identity_type = "spn"
2632
+ if instance .identity is not None :
2633
+ current_identity_type = instance .identity .type .casefold ()
2634
+
2635
+ goal_identity_type = current_identity_type
2636
+ if enable_managed_identity :
2637
+ if not assign_identity :
2638
+ goal_identity_type = "systemassigned"
2639
+ else :
2640
+ goal_identity_type = "userassigned"
2641
+
2642
+ if current_identity_type != goal_identity_type :
2643
+ msg = ""
2644
+ if current_identity_type == "spn" :
2645
+ msg = ('Your cluster is using service principal, and you are going to update '
2646
+ 'the cluster to use {} managed identity.\n After updating, your '
2647
+ 'cluster\' s control plane and addon pods will switch to use managed '
2648
+ 'identity, but kubelet will KEEP USING SERVICE PRINCIPAL '
2649
+ 'until you upgrade your agentpool.\n '
2650
+ 'Are you sure you want to perform this operation?' ).format (goal_identity_type )
2651
+ else :
2652
+ msg = ('Your cluster is already using {} managed identity, and you are going to '
2653
+ 'update the cluster to use {} managed identity. \n Are you sure you want to '
2654
+ 'perform this operation?' ).format (current_identity_type , goal_identity_type )
2655
+ if not yes and not prompt_y_n (msg , default = "n" ):
2656
+ return None
2657
+ if goal_identity_type == "systemassigned" :
2658
+ instance .identity = ManagedClusterIdentity (
2659
+ type = "SystemAssigned"
2660
+ )
2661
+ elif goal_identity_type == "userassigned" :
2662
+ user_assigned_identity = {
2663
+ assign_identity : ManagedClusterIdentityUserAssignedIdentitiesValue ()
2664
+ }
2665
+ instance .identity = ManagedClusterIdentity (
2666
+ type = "UserAssigned" ,
2667
+ user_assigned_identities = user_assigned_identity
2668
+ )
2669
+
2670
+ monitoring_addon_enabled = False
2671
+ ingress_appgw_addon_enabled = False
2672
+ virtual_node_addon_enabled = False
2673
+ if instance .addon_profiles is not None :
2674
+ monitoring_addon_enabled = CONST_MONITORING_ADDON_NAME in instance .addon_profiles and \
2675
+ instance .addon_profiles [CONST_MONITORING_ADDON_NAME ].enabled
2676
+ ingress_appgw_addon_enabled = CONST_INGRESS_APPGW_ADDON_NAME in instance .addon_profiles and \
2677
+ instance .addon_profiles [CONST_INGRESS_APPGW_ADDON_NAME ].enabled
2678
+ virtual_node_addon_enabled = CONST_VIRTUAL_NODE_ADDON_NAME + 'Linux' in instance .addon_profiles and \
2679
+ instance .addon_profiles [CONST_VIRTUAL_NODE_ADDON_NAME + 'Linux' ].enabled
2680
+
2681
+ return _put_managed_cluster_ensuring_permission (
2682
+ cmd ,
2683
+ client ,
2684
+ subscription_id ,
2685
+ resource_group_name ,
2686
+ name ,
2687
+ instance ,
2688
+ monitoring_addon_enabled ,
2689
+ ingress_appgw_addon_enabled ,
2690
+ virtual_node_addon_enabled ,
2691
+ False ,
2692
+ instance .agent_pool_profiles [0 ].vnet_subnet_id ,
2693
+ _is_msi_cluster (instance ),
2694
+ attach_acr ,
2695
+ None ,
2696
+ no_wait )
2659
2697
2660
2698
2661
2699
# pylint: disable=unused-argument,inconsistent-return-statements,too-many-return-statements
@@ -4113,3 +4151,80 @@ def _is_msi_cluster(managed_cluster):
4113
4151
return (managed_cluster and managed_cluster .identity and
4114
4152
(managed_cluster .identity .type .casefold () == "systemassigned" or
4115
4153
managed_cluster .identity .type .casefold () == "userassigned" ))
4154
+
4155
+
4156
+ def _put_managed_cluster_ensuring_permission (
4157
+ cmd , # pylint: disable=too-many-locals,too-many-statements,too-many-branches
4158
+ client ,
4159
+ subscription_id ,
4160
+ resource_group_name ,
4161
+ name ,
4162
+ managed_cluster ,
4163
+ monitoring_addon_enabled ,
4164
+ ingress_appgw_addon_enabled ,
4165
+ virtual_node_addon_enabled ,
4166
+ need_grant_vnet_permission_to_cluster_identity ,
4167
+ vnet_subnet_id ,
4168
+ enable_managed_identity ,
4169
+ attach_acr ,
4170
+ headers ,
4171
+ no_wait
4172
+ ):
4173
+ # some addons require post cluster creation role assigment
4174
+ need_post_creation_role_assignment = (monitoring_addon_enabled or
4175
+ ingress_appgw_addon_enabled or
4176
+ (enable_managed_identity and attach_acr ) or
4177
+ virtual_node_addon_enabled or
4178
+ need_grant_vnet_permission_to_cluster_identity )
4179
+ if need_post_creation_role_assignment :
4180
+ # adding a wait here since we rely on the result for role assignment
4181
+ cluster = LongRunningOperation (cmd .cli_ctx )(client .create_or_update (
4182
+ resource_group_name = resource_group_name ,
4183
+ resource_name = name ,
4184
+ parameters = managed_cluster ,
4185
+ custom_headers = headers ))
4186
+ cloud_name = cmd .cli_ctx .cloud .name
4187
+ # add cluster spn/msi Monitoring Metrics Publisher role assignment to publish metrics to MDM
4188
+ # mdm metrics is supported only in azure public cloud, so add the role assignment only in this cloud
4189
+ if monitoring_addon_enabled and cloud_name .lower () == 'azurecloud' :
4190
+ from msrestazure .tools import resource_id
4191
+ cluster_resource_id = resource_id (
4192
+ subscription = subscription_id ,
4193
+ resource_group = resource_group_name ,
4194
+ namespace = 'Microsoft.ContainerService' , type = 'managedClusters' ,
4195
+ name = name
4196
+ )
4197
+ _add_monitoring_role_assignment (cluster , cluster_resource_id , cmd )
4198
+ if ingress_appgw_addon_enabled :
4199
+ _add_ingress_appgw_addon_role_assignment (cluster , cmd )
4200
+ if virtual_node_addon_enabled :
4201
+ _add_virtual_node_role_assignment (cmd , cluster , vnet_subnet_id )
4202
+ if need_grant_vnet_permission_to_cluster_identity :
4203
+ if not _create_role_assignment (cmd .cli_ctx , 'Network Contributor' ,
4204
+ cluster .identity .principal_id , scope = vnet_subnet_id ,
4205
+ resolve_assignee = False ):
4206
+ logger .warning ('Could not create a role assignment for subnet. '
4207
+ 'Are you an Owner on this subscription?' )
4208
+
4209
+ if enable_managed_identity and attach_acr :
4210
+ # Attach ACR to cluster enabled managed identity
4211
+ if cluster .identity_profile is None or \
4212
+ cluster .identity_profile ["kubeletidentity" ] is None :
4213
+ logger .warning ('Your cluster is successfully created, but we failed to attach '
4214
+ 'acr to it, you can manually grant permission to the identity '
4215
+ 'named <ClUSTER_NAME>-agentpool in MC_ resource group to give '
4216
+ 'it permission to pull from ACR.' )
4217
+ else :
4218
+ kubelet_identity_client_id = cluster .identity_profile ["kubeletidentity" ].client_id
4219
+ _ensure_aks_acr (cmd .cli_ctx ,
4220
+ client_id = kubelet_identity_client_id ,
4221
+ acr_name_or_id = attach_acr ,
4222
+ subscription_id = subscription_id )
4223
+ else :
4224
+ cluster = sdk_no_wait (no_wait , client .create_or_update ,
4225
+ resource_group_name = resource_group_name ,
4226
+ resource_name = name ,
4227
+ parameters = managed_cluster ,
4228
+ custom_headers = headers )
4229
+
4230
+ return cluster
0 commit comments