From 1de51eea9678da84ac9b0ba3cc446094e7b2d07e Mon Sep 17 00:00:00 2001 From: Haroon Feisal <38823870+haroonf@users.noreply.github.com> Date: Thu, 7 Apr 2022 17:57:21 -0400 Subject: [PATCH] Marchp1s and add back Identity (#57) * Skeleton code * az containerapp env show * List kube/managed environments * Create kube environment, wait doesn't work yet * Update containerapp stubs (check if it is supported now) * Containerapp env delete, polling not working yet * Added polling for create and delete * Use Microsoft.App RP for show, list, delete command * Create containerapp env using Microsoft.App RP * Add optional containerapp env create arguments * Remove old kube environment code, naming fixes * Containerapp create almost done * Done containerapp create, except for --yaml. Need to test * Containerapp show, list * Fix helptext * Containerapp delete * Containerapp update. Needs secrets api to be implemented, and testing * Add scale command * Various validations, small fixes * listSecrets API for updates, autogen log analytics for env * Use space delimiter for secrets and env variables * Verify sub is registered to Microsoft.ContainerRegistration if creating vnet enabled env, remove logs-type parameter * Containerapp create --yaml * Fix updating registry to do create or update * Fix containerapp update command. Add image-name parameter to support multi container updates. Fix updating registries, containers and secrets * started update with --yaml. Need to do create or update for when an attribute is a list of items * use space delimiter for startup_command and args, instead of comma delimiter * Traffic weights * List and show revisions * az containerapp revision restart, activate, deactivate * Add ability for users to clear args/command in az containerapp update * Various fixes, traffic weights fixes * Verify subnet subscription is registered to Microsoft.ContainerServices * GitHub Actions Update (#17) * Added models. Finished transferring Calvin's previous work. * Updated wrong models. * Updated models in custom.py, added githubactionclient. * Updated envelope to be correct. * Small bug fixes. * Updated error handling. Fixed bugs. Initial working state. * Added better error handling. * Added error messages for tokens with inappropriate access rights. * Added back get_acr_cred. * Fixed problems from merge conflict. * Updated names of imports from ._models.py to fix pylance erros. * Removed random imports. Co-authored-by: Haroon Feisal * Remove --location since location must be same as managed env * Add options for flag names: --env-vars and --registry-srever * Empty string to clear env_vars * Default revisions_mode to single * Infer acr credentials if it is acr and credentials are not provided * fix help msg * if image is hosted on acr, and no registry server is supplied, infer the registry server * Added subgroups (Ingress, Registry, Secret) and updated revisions (#18) * Added ingress subgroup. * Added help for ingress. * Fixed ingress traffic help. * Added registry commands. * Updated registry remove util to clear secrets if none remaining. Added warning when updating existing registry. Added registry help. * Changed registry delete to remove. * Added error message if user tries to remove non assigned registry. * Changed registry add back to registry set. * Added secret subgroup commands. * Removed yaml support from secret set. * Changed secret add to secret set. Updated consistency between secret set and secret delete. Added secret help. Require at least one secret passed with --secrets for secret commands. * Changed param name for secret delete from --secrets to --secret-names. Updated help. * Changed registry remove to registry delete. * Fixed bug in registry delete. * Added revision mode set and revision copy. * Modified update_containerapp_yaml to support updating from non-current revision. Authored-by: Haroon Feisal * More p0 fixes (#20) * Remove --registry-login-server, only allow --registry-server * Rename --environment-variables to --env-vars * If no image is supplied, use default quickstart image * Update help text (#21) * Update help text * Update punctuation * master -> main * New 1.0.1 version * Added identity commands + --assign-identity flag to containerapp create (#8) * Added identity show and assign. * Finisheed identity remove. * Added helps, updated identity remove to work with identity names instead of requiring identity resource ids. * Moved helper function to utils. * Require --identities flag when removing identities. * Added message for assign identity with no specified identity. * Added --assign-identity flag to containerapp create. * Moved assign-identity flag to containerapp create. * Fixed small logic error on remove identities when passing duplicate identities. Added warnings for certain edge cases. * Updated param definition for identity assign --identity default. * Added identity examples in help. * Made sure secrets were not removed when assigning identities. Added tolerance for [system] passed with capital letters. * Fixed error from merge. Co-authored-by: Haroon Feisal * Dapr Commands (#23) * Added ingress subgroup. * Added help for ingress. * Fixed ingress traffic help. * Added registry commands. * Updated registry remove util to clear secrets if none remaining. Added warning when updating existing registry. Added registry help. * Changed registry delete to remove. * Added error message if user tries to remove non assigned registry. * Changed registry add back to registry set. * Added secret subgroup commands. * Removed yaml support from secret set. * Changed secret add to secret set. Updated consistency between secret set and secret delete. Added secret help. Require at least one secret passed with --secrets for secret commands. * Changed param name for secret delete from --secrets to --secret-names. Updated help. * Changed registry remove to registry delete. * Fixed bug in registry delete. * Added revision mode set and revision copy. * Added dapr enable and dapr disable. Need to test more. * Added list, show, set dapr component. Added dapr enable, disable. * Added delete dapr delete. * Added helps and param text. * Changed dapr delete to dapr remove to match with dapr set. * Commented out managed identity for whl file. * Uncommented. Co-authored-by: Haroon Feisal * Rename --image-name to --container-name * Remove allowInsecure since it was messing with the api parsing * Fix for env var being empty string * Rename to --dapr-instrumentation-key, only infer ACR credentials if --registry-server is provided * Remove az containerapp scale * Fix delete containerapp errors * Remove ingress, dapr flags from az containerapp update/revision copy * Fix revision list -o table * Help text fix * Bump extension to 0.1.2 * Update managed identities and Dapr help text (#25) * Update managed identities and Dapr help text * Update Dapr flags * Add secretref note * Env var options + various bug fixes (#26) * Moved dapr arguments to env as a subgroup. * Added env variable options. * Changed revision mode set to revision set-mode. * Added env var options to revision copy. * Fixed revision copy bug related to env secret refs. * Changed registry and secret delete to remove. Added registry param helps. Removed replica from table output and added trafficWeight. * Updating warning text. * Updated warning text once more. * Made name optional for revision copy if from-revision flag is passed. Co-authored-by: Haroon Feisal * Fixed style issues, various bug fixes (#27) * Moved dapr arguments to env as a subgroup. * Added env variable options. * Changed revision mode set to revision set-mode. * Added env var options to revision copy. * Fixed revision copy bug related to env secret refs. * Changed registry and secret delete to remove. Added registry param helps. Removed replica from table output and added trafficWeight. * Updating warning text. * Updated warning text once more. * Made name optional for revision copy if from-revision flag is passed. * Fixed whitespace style issues. * Styled clients and utils to pass pylint. * Finished client.py pylint fixes. * Fixed pylint issues. * Fixed flake8 commands and custom. * Fixed flake issues in src. * Added license header to _sdk_models. * Added confirmation for containerapp delete. Co-authored-by: Haroon Feisal * Update src/containerapp/azext_containerapp/tests/latest/test_containerapp_scenario.py Co-authored-by: Xing Zhou * Specific Error Types + Bugfixes (Help, remove app-subnet-resource-id, removed env-var alias, added help text for --name) (#28) * Moved dapr arguments to env as a subgroup. * Added env variable options. * Changed revision mode set to revision set-mode. * Added env var options to revision copy. * Fixed revision copy bug related to env secret refs. * Changed registry and secret delete to remove. Added registry param helps. Removed replica from table output and added trafficWeight. * Updating warning text. * Updated warning text once more. * Made name optional for revision copy if from-revision flag is passed. * Fixed whitespace style issues. * Styled clients and utils to pass pylint. * Finished client.py pylint fixes. * Fixed pylint issues. * Fixed flake8 commands and custom. * Fixed flake issues in src. * Added license header to _sdk_models. * Added confirmation for containerapp delete. * Update helps for identity, revision. Removed env-var alias for set-env-vars. Added name param help. * Removed app-subnet-resource-id. * Updated infrastructure subnet param help. * Check if containerapp resource exists before attempting to delete. * Added check before deleting managed env. * Changed error types to be more specific. * Removed check before deletion. Removed comments. Co-authored-by: Haroon Feisal * Reset to 0.1.0 version, remove unneeded options-list * Update min cli core version * Fixed style issues. (#30) Co-authored-by: Haroon Feisal * Fix linter issues * Use custom-show-command * Removed --ids from revision, secret, registry list. * Add linter exclusions * Fix polling on delete containerapp * Fix error handling * Add Container App Service * Fix flake linter * Fix help text * Mark extension as preview * Add python 3.9 and 3.10 as supported * Remove registries and secrets from az containerapp update, in favor of registry and secret subgroup * Fix YAML not working * Move import to inside deserialize function * Ingress enable --transport default. Secret list returns empty array. Secret update prints message saying user needs to restart their apps. Added show-values flag to secret list. Fixed yaml datetime field issues, replaced x00 values that also came up during testing. * Fixed dapr in create. * Revert "Ingress enable --transport default. Secret list returns empty array. Secret update prints message saying user needs to restart their apps. Added show-values flag to secret list. Fixed yaml datetime field issues, replaced x00 values that also came up during testing." This reverts commit 51bc543338f82584b6c74ff5296453b76e6749aa. * Revert "Fixed dapr in create." This reverts commit 37030adc542ab3e38264b29a01b284e29479f716. * Ingress enable --transport default. Secret list returns empty array. Secret update prints message saying user needs to restart their apps. Added show-values flag to secret list. Fixed yaml datetime field issues, replaced x00 values that also came up during testing. * Skeleton code * az containerapp env show * List kube/managed environments * Create kube environment, wait doesn't work yet * Update containerapp stubs (check if it is supported now) * Containerapp env delete, polling not working yet * Added polling for create and delete * Use Microsoft.App RP for show, list, delete command * Create containerapp env using Microsoft.App RP * Add optional containerapp env create arguments * Remove old kube environment code, naming fixes * Containerapp create almost done * Done containerapp create, except for --yaml. Need to test * Containerapp show, list * Fix helptext * Containerapp delete * Containerapp update. Needs secrets api to be implemented, and testing * Add scale command * Various validations, small fixes * listSecrets API for updates, autogen log analytics for env * Use space delimiter for secrets and env variables * Verify sub is registered to Microsoft.ContainerRegistration if creating vnet enabled env, remove logs-type parameter * Containerapp create --yaml * Fix updating registry to do create or update * Fix containerapp update command. Add image-name parameter to support multi container updates. Fix updating registries, containers and secrets * started update with --yaml. Need to do create or update for when an attribute is a list of items * use space delimiter for startup_command and args, instead of comma delimiter * Traffic weights * List and show revisions * az containerapp revision restart, activate, deactivate * Add ability for users to clear args/command in az containerapp update * Various fixes, traffic weights fixes * Verify subnet subscription is registered to Microsoft.ContainerServices * GitHub Actions Update (#17) * Added models. Finished transferring Calvin's previous work. * Updated wrong models. * Updated models in custom.py, added githubactionclient. * Updated envelope to be correct. * Small bug fixes. * Updated error handling. Fixed bugs. Initial working state. * Added better error handling. * Added error messages for tokens with inappropriate access rights. * Added back get_acr_cred. * Fixed problems from merge conflict. * Updated names of imports from ._models.py to fix pylance erros. * Removed random imports. Co-authored-by: Haroon Feisal * Remove --location since location must be same as managed env * Add options for flag names: --env-vars and --registry-srever * Empty string to clear env_vars * Default revisions_mode to single * Infer acr credentials if it is acr and credentials are not provided * fix help msg * if image is hosted on acr, and no registry server is supplied, infer the registry server * Added subgroups (Ingress, Registry, Secret) and updated revisions (#18) * Added ingress subgroup. * Added help for ingress. * Fixed ingress traffic help. * Added registry commands. * Updated registry remove util to clear secrets if none remaining. Added warning when updating existing registry. Added registry help. * Changed registry delete to remove. * Added error message if user tries to remove non assigned registry. * Changed registry add back to registry set. * Added secret subgroup commands. * Removed yaml support from secret set. * Changed secret add to secret set. Updated consistency between secret set and secret delete. Added secret help. Require at least one secret passed with --secrets for secret commands. * Changed param name for secret delete from --secrets to --secret-names. Updated help. * Changed registry remove to registry delete. * Fixed bug in registry delete. * Added revision mode set and revision copy. * Modified update_containerapp_yaml to support updating from non-current revision. Authored-by: Haroon Feisal * More p0 fixes (#20) * Remove --registry-login-server, only allow --registry-server * Rename --environment-variables to --env-vars * If no image is supplied, use default quickstart image * Update help text (#21) * Update help text * Update punctuation * master -> main * New 1.0.1 version * Added identity commands + --assign-identity flag to containerapp create (#8) * Added identity show and assign. * Finisheed identity remove. * Added helps, updated identity remove to work with identity names instead of requiring identity resource ids. * Moved helper function to utils. * Require --identities flag when removing identities. * Added message for assign identity with no specified identity. * Added --assign-identity flag to containerapp create. * Moved assign-identity flag to containerapp create. * Fixed small logic error on remove identities when passing duplicate identities. Added warnings for certain edge cases. * Updated param definition for identity assign --identity default. * Added identity examples in help. * Made sure secrets were not removed when assigning identities. Added tolerance for [system] passed with capital letters. * Fixed error from merge. Co-authored-by: Haroon Feisal * Dapr Commands (#23) * Added ingress subgroup. * Added help for ingress. * Fixed ingress traffic help. * Added registry commands. * Updated registry remove util to clear secrets if none remaining. Added warning when updating existing registry. Added registry help. * Changed registry delete to remove. * Added error message if user tries to remove non assigned registry. * Changed registry add back to registry set. * Added secret subgroup commands. * Removed yaml support from secret set. * Changed secret add to secret set. Updated consistency between secret set and secret delete. Added secret help. Require at least one secret passed with --secrets for secret commands. * Changed param name for secret delete from --secrets to --secret-names. Updated help. * Changed registry remove to registry delete. * Fixed bug in registry delete. * Added revision mode set and revision copy. * Added dapr enable and dapr disable. Need to test more. * Added list, show, set dapr component. Added dapr enable, disable. * Added delete dapr delete. * Added helps and param text. * Changed dapr delete to dapr remove to match with dapr set. * Commented out managed identity for whl file. * Uncommented. Co-authored-by: Haroon Feisal * Rename --image-name to --container-name * Remove allowInsecure since it was messing with the api parsing * Fix for env var being empty string * Rename to --dapr-instrumentation-key, only infer ACR credentials if --registry-server is provided * Remove az containerapp scale * Fix delete containerapp errors * Remove ingress, dapr flags from az containerapp update/revision copy * Fix revision list -o table * Help text fix * Bump extension to 0.1.2 * Update managed identities and Dapr help text (#25) * Update managed identities and Dapr help text * Update Dapr flags * Add secretref note * Env var options + various bug fixes (#26) * Moved dapr arguments to env as a subgroup. * Added env variable options. * Changed revision mode set to revision set-mode. * Added env var options to revision copy. * Fixed revision copy bug related to env secret refs. * Changed registry and secret delete to remove. Added registry param helps. Removed replica from table output and added trafficWeight. * Updating warning text. * Updated warning text once more. * Made name optional for revision copy if from-revision flag is passed. Co-authored-by: Haroon Feisal * Fixed style issues, various bug fixes (#27) * Moved dapr arguments to env as a subgroup. * Added env variable options. * Changed revision mode set to revision set-mode. * Added env var options to revision copy. * Fixed revision copy bug related to env secret refs. * Changed registry and secret delete to remove. Added registry param helps. Removed replica from table output and added trafficWeight. * Updating warning text. * Updated warning text once more. * Made name optional for revision copy if from-revision flag is passed. * Fixed whitespace style issues. * Styled clients and utils to pass pylint. * Finished client.py pylint fixes. * Fixed pylint issues. * Fixed flake8 commands and custom. * Fixed flake issues in src. * Added license header to _sdk_models. * Added confirmation for containerapp delete. Co-authored-by: Haroon Feisal * Update src/containerapp/azext_containerapp/tests/latest/test_containerapp_scenario.py Co-authored-by: Xing Zhou * Specific Error Types + Bugfixes (Help, remove app-subnet-resource-id, removed env-var alias, added help text for --name) (#28) * Moved dapr arguments to env as a subgroup. * Added env variable options. * Changed revision mode set to revision set-mode. * Added env var options to revision copy. * Fixed revision copy bug related to env secret refs. * Changed registry and secret delete to remove. Added registry param helps. Removed replica from table output and added trafficWeight. * Updating warning text. * Updated warning text once more. * Made name optional for revision copy if from-revision flag is passed. * Fixed whitespace style issues. * Styled clients and utils to pass pylint. * Finished client.py pylint fixes. * Fixed pylint issues. * Fixed flake8 commands and custom. * Fixed flake issues in src. * Added license header to _sdk_models. * Added confirmation for containerapp delete. * Update helps for identity, revision. Removed env-var alias for set-env-vars. Added name param help. * Removed app-subnet-resource-id. * Updated infrastructure subnet param help. * Check if containerapp resource exists before attempting to delete. * Added check before deleting managed env. * Changed error types to be more specific. * Removed check before deletion. Removed comments. Co-authored-by: Haroon Feisal * Reset to 0.1.0 version, remove unneeded options-list * Update min cli core version * Fixed style issues. (#30) Co-authored-by: Haroon Feisal * Fix linter issues * Use custom-show-command * Removed --ids from revision, secret, registry list. * Add linter exclusions * Fix polling on delete containerapp * Fix error handling * Add Container App Service * Fix flake linter * Fix help text * Mark extension as preview * Add python 3.9 and 3.10 as supported * Remove registries and secrets from az containerapp update, in favor of registry and secret subgroup * Fix YAML not working * Move import to inside deserialize function * Dapr moved from Template to Configuration * Use aka.ms link for containerapps yaml * Updated dapr enable/disable to current spec. * Fixed oversight. * Remove revisions-mode from containerapp update * Fixed dapr enable property names. (#47) Co-authored-by: Haroon Feisal * Fix exceptions with using --yaml in containerapp create/update * Rename history msg * Include fqdn in containerapp table output * Added ingress messages. * Revert history msg * Reduced redundant code between revision copy and containerapp update. * Fixed merge issues. * Fixed merge conflicts, moved helper function Co-authored-by: Calvin Chan Co-authored-by: Haroon Feisal Co-authored-by: Anthony Chu Co-authored-by: Xing Zhou --- src/containerapp/azext_containerapp/_help.py | 49 ++- .../azext_containerapp/_params.py | 7 + .../azext_containerapp/commands.py | 5 + src/containerapp/azext_containerapp/custom.py | 330 +++++++----------- 4 files changed, 193 insertions(+), 198 deletions(-) diff --git a/src/containerapp/azext_containerapp/_help.py b/src/containerapp/azext_containerapp/_help.py index 5e75c334d8..c4e500caf4 100644 --- a/src/containerapp/azext_containerapp/_help.py +++ b/src/containerapp/azext_containerapp/_help.py @@ -162,6 +162,14 @@ """ +helps['containerapp revision copy'] = """ + type: command + short-summary: Create a revision based on a previous revision. + examples: + - name: Create a revision based on a previous revision. + text: | + az containerapp revision copy -n MyContainerapp -g MyResourceGroup --cpu 0.75 --memory 1.5Gi +""" # Environment Commands helps['containerapp env'] = """ @@ -256,6 +264,45 @@ az containerapp env dapr-component remove -g MyResourceGroup --dapr-component-name MyDaprComponentName --name MyEnvironment """ +# Identity Commands +helps['containerapp identity'] = """ + type: group + short-summary: Commands to manage managed identities. +""" + +helps['containerapp identity assign'] = """ + type: command + short-summary: Assign managed identity to a container app. + long-summary: Managed identities can be user-assigned or system-assigned. + examples: + - name: Assign system identity. + text: | + az containerapp identity assign + - name: Assign user identity. + text: | + az containerapp identity assign --identities myAssignedId + - name: Assign system and user identity. + text: | + az containerapp identity assign --identities [system] myAssignedId +""" + +helps['containerapp identity remove'] = """ + type: command + short-summary: Remove a managed identity from a container app. + examples: + - name: Remove system identity. + text: | + az containerapp identity remove --identities [system] + - name: Remove system and user identity. + text: | + az containerapp identity remove --identities [system] myAssignedId +""" + +helps['containerapp identity show'] = """ + type: command + short-summary: Show managed identities of a container app. +""" + # Ingress Commands helps['containerapp ingress'] = """ type: group @@ -470,7 +517,7 @@ helps['containerapp dapr enable'] = """ type: command - short-summary: Enable Dapr for a container app. + short-summary: Enable Dapr for a container app. Updates existing values. examples: - name: Enable Dapr for a container app. text: | diff --git a/src/containerapp/azext_containerapp/_params.py b/src/containerapp/azext_containerapp/_params.py index 6e0ee6918d..c70de7f12a 100644 --- a/src/containerapp/azext_containerapp/_params.py +++ b/src/containerapp/azext_containerapp/_params.py @@ -75,6 +75,7 @@ def load_arguments(self, _): c.argument('transport', arg_type=get_enum_type(['auto', 'http', 'http2']), help="The transport protocol used for ingress traffic.") with self.argument_context('containerapp create') as c: + c.argument('assign_identity', nargs='+', help="Space-separated identities. Use '[system]' to refer to the system assigned identity.") c.argument('traffic_weights', nargs='*', options_list=['--traffic-weight'], help="A list of revision weight(s) for the container app. Space-separated values in 'revision_name=weight' format. For latest revision, use 'latest=weight'") with self.argument_context('containerapp scale') as c: @@ -112,6 +113,12 @@ def load_arguments(self, _): with self.argument_context('containerapp env show') as c: c.argument('name', name_type, help='Name of the Container Apps Environment.') + with self.argument_context('containerapp identity') as c: + c.argument('identities', nargs='+', help="Space-separated identities. Use '[system]' to refer to the system assigned identity.") + + with self.argument_context('containerapp identity assign') as c: + c.argument('identities', nargs='+', help="Space-separated identities. Use '[system]' to refer to the system assigned identity. Default is '[system]'.") + with self.argument_context('containerapp github-action add') as c: c.argument('repo_url', help='The GitHub repository to which the workflow file will be added. In the format: https://github.com//') c.argument('token', help='A Personal Access Token with write access to the specified repository. For more information: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line') diff --git a/src/containerapp/azext_containerapp/commands.py b/src/containerapp/azext_containerapp/commands.py index c5b924287f..dd6f2d067d 100644 --- a/src/containerapp/azext_containerapp/commands.py +++ b/src/containerapp/azext_containerapp/commands.py @@ -62,6 +62,11 @@ def load_command_table(self, _): g.custom_command('set', 'create_or_update_dapr_component') g.custom_command('remove', 'remove_dapr_component') + with self.command_group('containerapp identity') as g: + g.custom_command('assign', 'assign_managed_identity', supports_no_wait=True, exception_handler=ex_handler_factory()) + g.custom_command('remove', 'remove_managed_identity', supports_no_wait=True, exception_handler=ex_handler_factory()) + g.custom_show_command('show', 'show_managed_identity') + with self.command_group('containerapp github-action') as g: g.custom_command('add', 'create_or_update_github_action', exception_handler=ex_handler_factory()) g.custom_show_command('show', 'show_github_action', exception_handler=ex_handler_factory()) diff --git a/src/containerapp/azext_containerapp/custom.py b/src/containerapp/azext_containerapp/custom.py index 15cea81f0f..52620d08e1 100644 --- a/src/containerapp/azext_containerapp/custom.py +++ b/src/containerapp/azext_containerapp/custom.py @@ -292,7 +292,8 @@ def create_containerapp(cmd, startup_command=None, args=None, tags=None, - no_wait=False): + no_wait=False, + assign_identity=None): _validate_subscription_registered(cmd, "Microsoft.App") if yaml: @@ -309,6 +310,9 @@ def create_containerapp(cmd, if managed_env is None: raise RequiredArgumentMissingError('Usage error: --environment is required if not using --yaml') + if assign_identity is None: + assign_identity = [] + # Validate managed environment parsed_managed_env = parse_resource_id(managed_env) managed_env_name = parsed_managed_env['name'] @@ -374,6 +378,28 @@ def create_containerapp(cmd, config_def["registries"] = [registries_def] if registries_def is not None else None config_def["dapr"] = dapr_def + # Identity actions + identity_def = ManagedServiceIdentityModel + identity_def["type"] = "None" + + assign_system_identity = '[system]' in assign_identity + assign_user_identities = [x for x in assign_identity if x != '[system]'] + + if assign_system_identity and assign_user_identities: + identity_def["type"] = "SystemAssigned, UserAssigned" + elif assign_system_identity: + identity_def["type"] = "SystemAssigned" + elif assign_user_identities: + identity_def["type"] = "UserAssigned" + + if assign_user_identities: + identity_def["userAssignedIdentities"] = {} + subscription_id = get_subscription_id(cmd.cli_ctx) + + for r in assign_user_identities: + r = _ensure_identity_resource_id(subscription_id, resource_group_name, r) + identity_def["userAssignedIdentities"][r] = {} # pylint: disable=unsupported-assignment-operation + scale_def = None if min_replicas is not None or max_replicas is not None: scale_def = ScaleModel @@ -407,6 +433,7 @@ def create_containerapp(cmd, containerapp_def = ContainerAppModel containerapp_def["location"] = location + containerapp_def["identity"] = identity_def containerapp_def["properties"]["managedEnvironmentId"] = managed_env containerapp_def["properties"]["configuration"] = config_def containerapp_def["properties"]["template"] = template_def @@ -429,25 +456,26 @@ def create_containerapp(cmd, handle_raw_exception(e) -def update_containerapp(cmd, - name, - resource_group_name, - yaml=None, - image=None, - container_name=None, - min_replicas=None, - max_replicas=None, - set_env_vars=None, - remove_env_vars=None, - replace_env_vars=None, - remove_all_env_vars=False, - cpu=None, - memory=None, - revision_suffix=None, - startup_command=None, - args=None, - tags=None, - no_wait=False): +def update_containerapp_logic(cmd, + name, + resource_group_name, + yaml=None, + image=None, + container_name=None, + min_replicas=None, + max_replicas=None, + set_env_vars=None, + remove_env_vars=None, + replace_env_vars=None, + remove_all_env_vars=False, + cpu=None, + memory=None, + revision_suffix=None, + startup_command=None, + args=None, + tags=None, + no_wait=False, + from_revision=None): _validate_subscription_registered(cmd, "Microsoft.App") if yaml: @@ -455,7 +483,7 @@ def update_containerapp(cmd, set_env_vars or remove_env_vars or replace_env_vars or remove_all_env_vars or cpu or memory or\ startup_command or args or tags: logger.warning('Additional flags were passed along with --yaml. These flags will be ignored, and the configuration defined in the yaml will be used instead') - return update_containerapp_yaml(cmd=cmd, name=name, resource_group_name=resource_group_name, file_name=yaml, no_wait=no_wait) + return update_containerapp_yaml(cmd=cmd, name=name, resource_group_name=resource_group_name, file_name=yaml, no_wait=no_wait, from_revision=from_revision) containerapp_def = None try: @@ -466,6 +494,16 @@ def update_containerapp(cmd, if not containerapp_def: raise ResourceNotFoundError("The containerapp '{}' does not exist".format(name)) + if from_revision: + try: + r = ContainerAppClient.show_revision(cmd=cmd, resource_group_name=resource_group_name, container_app_name=name, name=from_revision) + except CLIError as e: + # Error handle the case where revision not found? + handle_raw_exception(e) + + _update_revision_env_secretrefs(r["properties"]["template"]["containers"], name) + containerapp_def["properties"]["template"] = r["properties"]["template"] + # Doing this while API has bug. If env var is an empty string, API doesn't return "value" even though the "value" should be an empty string if "properties" in containerapp_def and "template" in containerapp_def["properties"] and "containers" in containerapp_def["properties"]["template"]: for container in containerapp_def["properties"]["template"]["containers"]: @@ -613,6 +651,48 @@ def update_containerapp(cmd, handle_raw_exception(e) +def update_containerapp(cmd, + name, + resource_group_name, + yaml=None, + image=None, + container_name=None, + min_replicas=None, + max_replicas=None, + set_env_vars=None, + remove_env_vars=None, + replace_env_vars=None, + remove_all_env_vars=False, + cpu=None, + memory=None, + revision_suffix=None, + startup_command=None, + args=None, + tags=None, + no_wait=False): + _validate_subscription_registered(cmd, "Microsoft.App") + + return update_containerapp_logic(cmd, + name, + resource_group_name, + yaml, + image, + container_name, + min_replicas, + max_replicas, + set_env_vars, + remove_env_vars, + replace_env_vars, + remove_all_env_vars, + cpu, + memory, + revision_suffix, + startup_command, + args, + tags, + no_wait) + + def show_containerapp(cmd, name, resource_group_name): _validate_subscription_registered(cmd, "Microsoft.App") @@ -1195,177 +1275,26 @@ def copy_revision(cmd, if not name: name = _get_app_from_revision(from_revision) - if yaml: - if image or min_replicas or max_replicas or\ - set_env_vars or replace_env_vars or remove_env_vars or \ - remove_all_env_vars or cpu or memory or \ - startup_command or args or tags: - logger.warning('Additional flags were passed along with --yaml. These flags will be ignored, and the configuration defined in the yaml will be used instead') - return update_containerapp_yaml(cmd=cmd, name=name, resource_group_name=resource_group_name, file_name=yaml, from_revision=from_revision, no_wait=no_wait) - - containerapp_def = None - try: - containerapp_def = ContainerAppClient.show(cmd=cmd, resource_group_name=resource_group_name, name=name) - except: - pass - - if not containerapp_def: - raise ResourceNotFoundError("The containerapp '{}' does not exist".format(name)) - - if from_revision: - try: - r = ContainerAppClient.show_revision(cmd=cmd, resource_group_name=resource_group_name, container_app_name=name, name=from_revision) - except CLIError as e: - # Error handle the case where revision not found? - handle_raw_exception(e) - - _update_revision_env_secretrefs(r["properties"]["template"]["containers"], name) - containerapp_def["properties"]["template"] = r["properties"]["template"] - - # Doing this while API has bug. If env var is an empty string, API doesn't return "value" even though the "value" should be an empty string - if "properties" in containerapp_def and "template" in containerapp_def["properties"] and "containers" in containerapp_def["properties"]["template"]: - for container in containerapp_def["properties"]["template"]["containers"]: - if "env" in container: - for e in container["env"]: - if "value" not in e: - e["value"] = "" - - update_map = {} - update_map['scale'] = min_replicas or max_replicas - update_map['container'] = image or container_name or set_env_vars or replace_env_vars or remove_env_vars or remove_all_env_vars or cpu or memory or startup_command is not None or args is not None - - if tags: - _add_or_update_tags(containerapp_def, tags) - - if revision_suffix is not None: - containerapp_def["properties"]["template"]["revisionSuffix"] = revision_suffix - - # Containers - if update_map["container"]: - if not container_name: - if len(containerapp_def["properties"]["template"]["containers"]) == 1: - container_name = containerapp_def["properties"]["template"]["containers"][0]["name"] - else: - raise ValidationError("Usage error: --image-name is required when adding or updating a container") - - # Check if updating existing container - updating_existing_container = False - for c in containerapp_def["properties"]["template"]["containers"]: - if c["name"].lower() == container_name.lower(): - updating_existing_container = True - - if image is not None: - c["image"] = image - - if set_env_vars is not None: - if "env" not in c or not c["env"]: - c["env"] = [] - # env vars - _add_or_update_env_vars(c["env"], parse_env_var_flags(set_env_vars), is_add=True) - - if replace_env_vars is not None: - if "env" not in c or not c["env"]: - c["env"] = [] - # env vars - _add_or_update_env_vars(c["env"], parse_env_var_flags(replace_env_vars)) - - if remove_env_vars is not None: - if "env" not in c or not c["env"]: - c["env"] = [] - # env vars - _remove_env_vars(c["env"], remove_env_vars) - - if remove_all_env_vars: - c["env"] = [] - - if startup_command is not None: - if isinstance(startup_command, list) and not startup_command: - c["command"] = None - else: - c["command"] = startup_command - if args is not None: - if isinstance(args, list) and not args: - c["args"] = None - else: - c["args"] = args - if cpu is not None or memory is not None: - if "resources" in c and c["resources"]: - if cpu is not None: - c["resources"]["cpu"] = cpu - if memory is not None: - c["resources"]["memory"] = memory - else: - c["resources"] = { - "cpu": cpu, - "memory": memory - } - - # If not updating existing container, add as new container - if not updating_existing_container: - if image is None: - raise ValidationError("Usage error: --image is required when adding a new container") - - resources_def = None - if cpu is not None or memory is not None: - resources_def = ContainerResourcesModel - resources_def["cpu"] = cpu - resources_def["memory"] = memory - - container_def = ContainerModel - container_def["name"] = container_name - container_def["image"] = image - - if set_env_vars is not None: - # env vars - _add_or_update_env_vars(container_def["env"], parse_env_var_flags(set_env_vars), is_add=True) - - if replace_env_vars is not None: - # env vars - _add_or_update_env_vars(container_def["env"], parse_env_var_flags(replace_env_vars)) - - if remove_env_vars is not None: - # env vars - _remove_env_vars(container_def["env"], remove_env_vars) - - if remove_all_env_vars: - container_def["env"] = [] - - if startup_command is not None: - if isinstance(startup_command, list) and not startup_command: - container_def["command"] = None - else: - container_def["command"] = startup_command - if args is not None: - if isinstance(args, list) and not args: - container_def["args"] = None - else: - container_def["args"] = args - if resources_def is not None: - container_def["resources"] = resources_def - - containerapp_def["properties"]["template"]["containers"].append(container_def) - - # Scale - if update_map["scale"]: - if "scale" not in containerapp_def["properties"]["template"]: - containerapp_def["properties"]["template"]["scale"] = {} - if min_replicas is not None: - containerapp_def["properties"]["template"]["scale"]["minReplicas"] = min_replicas - if max_replicas is not None: - containerapp_def["properties"]["template"]["scale"]["maxReplicas"] = max_replicas - - _get_existing_secrets(cmd, resource_group_name, name, containerapp_def) - - try: - r = ContainerAppClient.create_or_update( - cmd=cmd, resource_group_name=resource_group_name, name=name, container_app_envelope=containerapp_def, no_wait=no_wait) - - if "properties" in r and "provisioningState" in r["properties"] and r["properties"]["provisioningState"].lower() == "waiting" and not no_wait: - logger.warning('Containerapp update in progress. Please monitor the update using `az containerapp show -n {} -g {}`'.format(name, resource_group_name)) - - return r - except Exception as e: - handle_raw_exception(e) + return update_containerapp_logic(cmd, + name, + resource_group_name, + yaml, + image, + container_name, + min_replicas, + max_replicas, + set_env_vars, + remove_env_vars, + replace_env_vars, + remove_all_env_vars, + cpu, + memory, + revision_suffix, + startup_command, + args, + tags, + no_wait, + from_revision) def set_revision_mode(cmd, resource_group_name, name, mode, no_wait=False): @@ -1410,7 +1339,7 @@ def show_ingress(cmd, name, resource_group_name): raise ValidationError("The containerapp '{}' does not have ingress enabled.".format(name)) from e -def enable_ingress(cmd, name, resource_group_name, type, target_port, transport, allow_insecure=False, no_wait=False): # pylint: disable=redefined-builtin +def enable_ingress(cmd, name, resource_group_name, type, target_port, transport="auto", allow_insecure=False, no_wait=False): # pylint: disable=redefined-builtin _validate_subscription_registered(cmd, "Microsoft.App") containerapp_def = None @@ -1688,22 +1617,28 @@ def remove_registry(cmd, name, resource_group_name, server, no_wait=False): pass -def list_secrets(cmd, name, resource_group_name): +def list_secrets(cmd, name, resource_group_name, show_values=False): _validate_subscription_registered(cmd, "Microsoft.App") containerapp_def = None try: - containerapp_def = ContainerAppClient.show(cmd=cmd, resource_group_name=resource_group_name, name=name) + r = containerapp_def = ContainerAppClient.show(cmd=cmd, resource_group_name=resource_group_name, name=name) except: pass if not containerapp_def: raise ResourceNotFoundError("The containerapp '{}' does not exist".format(name)) + if not show_values: + try: + return r["properties"]["configuration"]["secrets"] + except: + return [] try: return ContainerAppClient.list_secrets(cmd=cmd, resource_group_name=resource_group_name, name=name)["value"] - except Exception as e: - raise ValidationError("The containerapp {} has no assigned secrets.".format(name)) from e + except Exception: + return [] + # raise ValidationError("The containerapp {} has no assigned secrets.".format(name)) from e def show_secret(cmd, name, resource_group_name, secret_name): @@ -1796,6 +1731,7 @@ def set_secrets(cmd, name, resource_group_name, secrets, try: r = ContainerAppClient.create_or_update( cmd=cmd, resource_group_name=resource_group_name, name=name, container_app_envelope=containerapp_def, no_wait=no_wait) + logger.warning("Containerapp must be restarted in order for secret changes to take effect.") return r["properties"]["configuration"]["secrets"] except Exception as e: handle_raw_exception(e)