Skip to content

Commit

Permalink
Modified help text (Azure#4)
Browse files Browse the repository at this point in the history
* Adding patch list

* Added patch list command

* Revert thumbprint arg

* Fix bugs

* Integrated with Harry

* Fixed bug

* Fixed command usage text

* Made managed env optional

* Fixed identation

* Fixed identation

* Made env optional

* Remove patch list

* Update help text for patch list and patch run

* Modified help text

* Made resouce group optional

* Added custom telemetry

* Fixed linting errors

---------

Co-authored-by: harrli <harrli@microsoft.com>
Co-authored-by: Harry Li <110055355+harryli0108@users.noreply.github.com>
  • Loading branch information
3 people committed May 11, 2023
1 parent a4c81ae commit 5cbaa2f
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 32 deletions.
24 changes: 21 additions & 3 deletions src/containerapp/azext_containerapp/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -1272,14 +1272,32 @@
--compose-file-path "path/to/docker-compose.yml"
"""

#Patch commands
helps['containerapp patch'] = """
type: group
short-summary: Patch Azure Container Apps.
"""

helps['containerapp patch list'] = """
type: command
short-summary: List Container Apps to be patched.Patching is only available for the apps built using the source to cloud feature.
exmaples:
- name: List Container Apps that can be patched.
text: |
az containerapp patch -g MyResourceGroup --environment MyContainerappEnv
- name: List patchable and unpatchable Container Apps.
text: |
az containerapp patch -g MyResourceGroup --environment MyContainerappEnv --show-all
"""

helps['containerapp patch run'] = """
type: command
short-summary: List and select container apps to be patched.
short-summary: List and select Container Apps to be patched.Patching is only available for the apps built using the source to cloud feature.
exmaples:
- name: Show containerapps that can be patched and apply patch.
- name: List Container Apps that can be patched and apply patch.
text: |
az containerapp patch -g MyResourceGroup --environment MyContainerappEnv
- name: Show patchable and unpatchable containerapps and apply patch.
- name: List patchable and unpatchable Container Apps and apply patch.
text: |
az containerapp patch -g MyResourceGroup --environment MyContainerappEnv --show-all
"""
14 changes: 10 additions & 4 deletions src/containerapp/azext_containerapp/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,13 @@ def load_arguments(self, _):
c.argument('min_nodes', help="The minimum node count for the workload profile")
c.argument('max_nodes', help="The maximum node count for the workload profile")

with self.argument_context('containerapp patch') as c:
c.argument('resource_group_name', options_list=['--rg','-g'], configured_default='resource_group_name', id_part=None)
c.argument('environment', options_list=['--environment', '-e'], help='Name or resource id of the Container App environment.')
c.argument('show_all', options_list=['--show-all'],help='Show all patchable and unpatchable containerapps')
with self.argument_context('containerapp patch list') as c:
c.argument('resource_group_name', arg_type=resource_group_name_type)
c.argument('managed_env',options_list=['--environment','-e'],help='Name or resource id of the Container App environment.')
c.argument('show_all', options_list=['--show-all'],help='Show all patchable and unpatchable Container Apps')

with self.argument_context('containerapp patch run') as c:
c.argument('resource_group_name', arg_type=resource_group_name_type)
c.argument('managed_env',validator=validate_managed_env_name_or_id, options_list=['--environment', '-e'], help='Name or resource id of the Container App environment.')
c.argument('show_all', options_list=['--show-all'],help='Show all patchable and unpatchable Container Apps')

1 change: 1 addition & 0 deletions src/containerapp/azext_containerapp/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1781,6 +1781,7 @@ def patchableCheck(repoTagSplit: str, oryxBuilderRunImgTags, bom):
result = {
"targetContainerAppName": bom["targetContainerAppName"],
"targetContainerName": bom["targetContainerName"],
"targetContainerAppEnvironmentName": bom["targetContainerAppEnvironmentName"],
"revisionMode": bom["revisionMode"],
"targetImageName": bom["image_name"],
"oldRunImage": repoTagSplit,
Expand Down
6 changes: 5 additions & 1 deletion src/containerapp/azext_containerapp/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ def load_command_table(self, _):
g.custom_command('exec', 'containerapp_ssh', validator=validate_ssh)
g.custom_command('up', 'containerapp_up', supports_no_wait=False, exception_handler=ex_handler_factory())
g.custom_command('browse', 'open_containerapp_in_browser')
g.custom_command('patch','patch_run', isPreview=True)

with self.command_group('containerapp replica') as g:
g.custom_show_command('show', 'get_replica') # TODO implement the table transformer
Expand Down Expand Up @@ -200,3 +199,8 @@ def load_command_table(self, _):
g.custom_show_command('show', 'show_workload_profile')
g.custom_command('set', 'set_workload_profile')
g.custom_command('delete', 'delete_workload_profile')

with self.command_group('containerapp patch', is_preview=True) as g:
g.custom_command('list','patch_list',is_preview=True)
g.custom_command('run','patch_run',is_preview=True)

54 changes: 30 additions & 24 deletions src/containerapp/azext_containerapp/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import requests
import json
import subprocess
from azure.cli.core import telemetry as telemetry_core

from azure.cli.core.azclierror import (
RequiredArgumentMissingError,
Expand All @@ -30,6 +31,7 @@
from msrestazure.tools import parse_resource_id, is_valid_resource_id
from msrest.exceptions import DeserializationError


from ._client_factory import handle_raw_exception, handle_non_404_exception
from ._clients import ManagedEnvironmentClient, ContainerAppClient, GitHubActionClient, DaprComponentClient, StorageClient, AuthClient, WorkloadProfileClient
from ._github_oauth import get_github_access_token
Expand Down Expand Up @@ -4133,7 +4135,7 @@ def show_auth_config(cmd, resource_group_name, name):
return auth_settings

# Compose

def create_containerapps_from_compose(cmd, # pylint: disable=R0914
resource_group_name,
managed_env,
Expand Down Expand Up @@ -4303,7 +4305,7 @@ def delete_workload_profile(cmd, resource_group_name, env_name, workload_profile


def patch_list(cmd, resource_group_name, managed_env=None, show_all=False):
if(managed_env):
if managed_env:
caList = list_containerapp(cmd, resource_group_name, managed_env)
else:
envList = list_managed_environments(cmd, resource_group_name)
Expand All @@ -4320,7 +4322,7 @@ def patch_list(cmd, resource_group_name, managed_env=None, show_all=False):
containers = ca["properties"]["template"]["containers"]
for container in containers:
result = dict(imageName=container["image"], targetContainerName=container["name"], targetContainerAppName=ca["name"], targetContainerAppEnvironmentName = managedEnvName, revisionMode=ca["properties"]["configuration"]["activeRevisionsMode"])
imgs.append(result)
imgs.append(result)
# Get the BOM of the images
results = []
boms = []
Expand Down Expand Up @@ -4371,7 +4373,7 @@ def patch_list(cmd, resource_group_name, managed_env=None, show_all=False):
else:
for runImagesProp in runImagesProps:
# result = None
if (runImagesProp["name"].find("mcr.microsoft.com/oryx/builder") != -1):
if runImagesProp["name"].find("mcr.microsoft.com/oryx/builder") != -1:
runImagesProp = runImagesProp["name"].split(":")
runImagesTag = runImagesProp[1]
# Based on Mariners
Expand All @@ -4381,17 +4383,19 @@ def patch_list(cmd, resource_group_name, managed_env=None, show_all=False):
results["NotPatchable"].append(checkResult)
else:
results[checkResult["id"]] = checkResult
else:
results["NotPatchable"].append(dict(targetContainerName=bom["targetContainerName"], targetContainerAppName=bom["targetContainerAppName"],targetContainerAppEnvironmentName=bom["targetContainerAppEnvironmentName"], revisionMode=bom["revisionMode"], targetImageName=bom["image_name"], oldRunImage=bom["remote_info"]["run_images"]["name"], newRunImage=None, id=None, reason=failedReason))
results.append(dict(targetContainerAppName=bom["targetContainerAppName"],targetContainerAppEnvironmentName=bom["targetContainerAppEnvironmentName"], oldRunImage=bom["remote_info"]["run_images"], newRunImage=None, id=None, reason=failedReason))
else:
results["NotPatchable"].append(dict(targetContainerName=bom["targetContainerName"], targetContainerAppName=bom["targetContainerAppName"],targetContainerAppEnvironmentName = bom["targetContainerAppEnvironmentName"], revisionMode=bom["revisionMode"], targetImageName=bom["image_name"], oldRunImage=bom["remote_info"]["run_images"]["name"], newRunImage=None, id=None, reason=failedReason))
results.append(dict(targetContainerAppName=bom["targetContainerAppName"],targetContainerAppEnvironmentName = bom["targetContainerAppEnvironmentName"], oldRunImage=bom["remote_info"]["run_images"], newRunImage=None, id=None, reason=failedReason))
else:
# Not based on image from mcr.microsoft.com/dotnet
results.append(dict(targetContainerAppName=bom["targetContainerAppName"],targetContainerAppEnvironmentName=bom["targetContainerAppEnvironmentName"], oldRunImage=bom["remote_info"]["run_images"], newRunImage=None, id=None, reason=mcrCheckReason))
if show_all == False :
results.append(dict(targetContainerAppName=bom["targetContainerAppName"],targetContainerAppEnvironmentName=bom["targetContainerAppEnvironmentName"], oldRunImage=bom["remote_info"]["run_images"], newRunImage=None, id=None, reason=mcrCheckReason))
if not show_all == False :
results = {k: v for k, v in results.items() if k != "NotPatchable"}
if not results :
print("No Container App available to patch at this time.");return
return results

def patch_run(cmd, resource_group_name, managed_env=None, show_all=False):
def patch_run(cmd, resource_group_name=None, managed_env=None, show_all=False):
patchable_check_results = patch_list(cmd, resource_group_name, managed_env, show_all=show_all)
patchable_result_key_list = list(patchable_check_results.keys())
if len(patchable_result_key_list) == 0 or patchable_result_key_list == ["NotPatchable"]:
Expand All @@ -4403,6 +4407,8 @@ def patch_run(cmd, resource_group_name, managed_env=None, show_all=False):
patchable_check_results_json = json.dumps(patchable_check_results, indent=4)
print(patchable_check_results_json)
user_input=input("Do you want to apply all the patch or specify by id? (y/n/id)\n")
if user_input == "y":
telemetry_core.add_extension_event('patch-run')
return patch_apply(cmd, patchable_check_results, user_input, resource_group_name)

def patch_apply(cmd, patchCheckList, method, resource_group_name):
Expand All @@ -4412,23 +4418,23 @@ def patch_apply(cmd, patchCheckList, method, resource_group_name):
for key in patchCheckList.keys():
if key != "NotPatchable":
if patchCheckList[key]["newRunImage"]:
results.append(patch_cli_call(cmd,
results.append(patch_cli_call(cmd,
resource_group_name,
patchCheckList[key]["targetContainerAppName"],
patchCheckList[key]["targetContainerName"],
patchCheckList[key]["targetImageName"],
patchCheckList[key]["newRunImage"],
patchCheckList[key]["targetContainerAppName"],
patchCheckList[key]["targetContainerName"],
patchCheckList[key]["targetImageName"],
patchCheckList[key]["newRunImage"],
patchCheckList[key]["revisionMode"]))
elif m == "n":
print("No patch applied."); return
else:
if method in patchCheckList.keys():
results.append(patch_cli_call(cmd,
results.append(patch_cli_call(cmd,
resource_group_name,
patchCheckList[method]["targetContainerAppName"],
patchCheckList[method]["targetContainerName"],
patchCheckList[method]["targetImageName"],
patchCheckList[method]["newRunImage"],
patchCheckList[method]["targetContainerAppName"],
patchCheckList[method]["targetContainerName"],
patchCheckList[method]["targetImageName"],
patchCheckList[method]["newRunImage"],
patchCheckList[method]["revisionMode"]))
else:
print("Invalid patch method or id."); return
Expand All @@ -4447,10 +4453,10 @@ def patch_cli_call(cmd, resource_group, container_app_name, container_name, targ
raise
try:
print("Patching container app: " + container_app_name + " container: " + container_name + " with image: " + new_target_image_name)
update_info_json = update_containerapp(cmd,
name=container_app_name,
resource_group_name=resource_group,
container_name=container_name,
update_info_json = update_containerapp(cmd,
name=container_app_name,
resource_group_name=resource_group,
container_name=container_name,
image=new_target_image_name)
print("Container app revision created successfully.")
## TODO: activate revision, fix the error when running the following two lines
Expand Down

0 comments on commit 5cbaa2f

Please sign in to comment.