Skip to content

Commit

Permalink
Remove patch list + make managed env optional (#3)
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

---------

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

helps['containerapp patch list'] = """
helps['containerapp patch'] = """
type: command
short-summary: List patchable and unpatchable container apps.
examples:
- name: List patchable container apps.
text: |
az containerapp list -g MyResourceGroup --environment MyContainerappEnv
- name: List patchable and non-patchable container apps.
text: |
az containerapp list -g MyResourceGroup --environment MyContainerappEnv --show-all
"""

helps['containerapp patch run'] = """
type: command
short-summary: List and choose container apps to be patched.
short-summary: List and select container apps to be patched.
exmaples:
- name: Patch a container app.
- name: Show containerapps that can be patched and apply patch.
text: |
az containerapp patch -g MyResourceGroup --environment MyContainerappEnv
- name: Patch a container app and show scan results of all container apps.
- name: Show patchable and unpatchable containerapps and apply patch.
text: |
az containerapp patch -g MyResourceGroup --environment MyContainerappEnv --show-all
"""
11 changes: 3 additions & 8 deletions src/containerapp/azext_containerapp/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,12 +415,7 @@ 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 list') as c:
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'], help='Name or resource id of the Container App environment.')
c.argument('show_all', options_list=['--show-all'],help='Show all patchable and non-patchable containerapps')

with self.argument_context('containerapp patch run') 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'], help='Name or resource id of the Container App environment.')
c.argument('show_all', options_list=['--show-all'],help='Show all patchable and non-patchable containerapps')
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')
4 changes: 0 additions & 4 deletions src/containerapp/azext_containerapp/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1722,7 +1722,6 @@ def format_location(location=None):
return location.lower().replace(" ", "").replace("(", "").replace(")", "")
return location


def is_docker_running():
# check to see if docker is running
client = None
Expand Down Expand Up @@ -1776,7 +1775,6 @@ def get_pack_exec_path():

return ""


def patchableCheck(repoTagSplit: str, oryxBuilderRunImgTags, bom):
tagProp = parseOryxMarinerTag(repoTagSplit)
if tagProp is None:
Expand Down Expand Up @@ -1839,7 +1837,6 @@ def patchableCheck(repoTagSplit: str, oryxBuilderRunImgTags, bom):
}
return result


def getCurrentMarinerTags() -> list(OryxMarinerRunImgTagProperty):
r = requests.get("https://mcr.microsoft.com/v2/oryx/builder/tags/list")
tags = r.json()
Expand Down Expand Up @@ -1870,7 +1867,6 @@ def getCurrentMarinerTags() -> list(OryxMarinerRunImgTagProperty):
tagList[framework] = {majorMinorVer: {support: {marinerVer: [tagObj]}}}
return tagList


def parseOryxMarinerTag(tag: str) -> OryxMarinerRunImgTagProperty:
tagSplit = tag.split("-")
if tagSplit[0] == "run" and tagSplit[1] == "dotnet":
Expand Down
5 changes: 1 addition & 4 deletions src/containerapp/azext_containerapp/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ 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 @@ -199,7 +200,3 @@ 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')
g.custom_command('run', 'patch_run')
45 changes: 27 additions & 18 deletions src/containerapp/azext_containerapp/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -4301,16 +4301,26 @@ def delete_workload_profile(cmd, resource_group_name, env_name, workload_profile
except Exception as e:
handle_raw_exception(e)

def patch_list(cmd, resource_group_name, managed_env, show_all=False):
caList = list_containerapp(cmd, resource_group_name, managed_env)

def patch_list(cmd, resource_group_name, managed_env=None, show_all=False):
if(managed_env):
caList = list_containerapp(cmd, resource_group_name, managed_env)
else:
envList = list_managed_environments(cmd, resource_group_name)
envNames = []
for env in envList:
envNames.append(env["name"])
caList = []
for envName in envNames:
caList+= list_containerapp(cmd,resource_group_name, envName)
imgs = []
if caList:
for ca in caList:
managedEnvName = ca["properties"]["managedEnvironmentId"].split('/')[-1]
containers = ca["properties"]["template"]["containers"]
for container in containers:
result = dict(imageName=container["image"], targetContainerName=container["name"], targetContainerAppName=ca["name"], revisionMode=ca["properties"]["configuration"]["activeRevisionsMode"])
imgs.append(result)

result = dict(imageName=container["image"], targetContainerName=container["name"], targetContainerAppName=ca["name"], targetContainerAppEnvironmentName = managedEnvName, revisionMode=ca["properties"]["configuration"]["activeRevisionsMode"])
imgs.append(result)
# Get the BOM of the images
results = []
boms = []
Expand All @@ -4319,7 +4329,7 @@ def patch_list(cmd, resource_group_name, managed_env, show_all=False):
#
for img in imgs:
if (img["imageName"].find("run-dotnet") != -1) and (img["imageName"].find("cbl-mariner") != -1):
bom = { "remote_info": { "run_images": [{ "name": "mcr.microsoft.com/oryx/builder:" + img["imageName"].split(":")[-1] }] }, "image_name": img["imageName"], "targetContainerName": img["targetContainerName"], "targetContainerAppName": img["targetContainerAppName"], "revisionMode": img["revisionMode"] }
bom = { "remote_info": { "run_images": [{ "name": "mcr.microsoft.com/oryx/builder:" + img["imageName"].split(":")[-1] }] }, "image_name": img["imageName"], "targetContainerName": img["targetContainerName"], "targetContainerAppName": img["targetContainerAppName"], "targetContainerAppEnvironmentName": img["targetContainerAppEnvironmentName"], "revisionMode": img["revisionMode"] }
else:
subprocess.run("pack inspect-image " + img["imageName"] + " --output json > ./bom.json 2>&1", shell=True)
with open("./bom.json", "rb") as f:
Expand All @@ -4329,11 +4339,11 @@ def patch_list(cmd, resource_group_name, managed_env, show_all=False):
bom = dict(remote_info=401, image_name=img["imageName"])
else:
bom = json.loads(lines)
bom.update({ "targetContainerName": img["targetContainerName"], "targetContainerAppName": img["targetContainerAppName"], "revisionMode": img["revisionMode"] })
bom.update({ "targetContainerName": img["targetContainerName"], "targetContainerAppName": img["targetContainerAppName"], "targetContainerAppEnvironmentName":img["targetContainerAppEnvironmentName"],"revisionMode": img["revisionMode"] })

boms.append(bom)

# # For testing

# with open("./bom.json", "rb") as f:
# lines = f.read()
# # if lines.find(b"status code 401 Unauthorized") == -1 or lines.find(b"unable to find image") == -1:
Expand All @@ -4352,13 +4362,12 @@ def patch_list(cmd, resource_group_name, managed_env, show_all=False):
# Start checking if the images are based on Mariner
for bom in boms:
if bom["remote_info"] == 401:
results["NotPatchable"].append(dict(targetContainerName=bom["targetContainerName"], targetContainerAppName=bom["targetContainerAppName"], revisionMode=bom["revisionMode"], targetImageName=bom["image_name"], oldRunImage=None, newRunImage=None, id=None, reason=failedReason))
results["NotPatchable"].append(dict(targetContainerName=bom["targetContainerName"], targetContainerAppName=bom["targetContainerAppName"],targetContainerAppEnvironmentName=bom["targetContainerAppEnvironmentName"], revisionMode=bom["revisionMode"], targetImageName=bom["image_name"], oldRunImage=None, newRunImage=None, id=None, reason=failedReason))
else:
# devide run-images into different parts by "/"
runImagesProps = bom["remote_info"]["run_images"]
if runImagesProps is None:

results["NotPatchable"].append(dict(targetContainerName=bom["targetContainerName"], targetContainerAppName=bom["targetContainerAppName"], revisionMode=bom["revisionMode"], targetImageName=bom["image_name"], oldRunImage=None, newRunImage=None, id=None, reason=notBasedMarinerReason))
results["NotPatchable"].append(dict(targetContainerName=bom["targetContainerName"], targetContainerAppName=bom["targetContainerAppName"],targetContainerAppEnvironmentName=bom["targetContainerAppEnvironmentName"], revisionMode=bom["revisionMode"], targetImageName=bom["image_name"], oldRunImage=None, newRunImage=None, id=None, reason=notBasedMarinerReason))
else:
for runImagesProp in runImagesProps:
# result = None
Expand All @@ -4373,21 +4382,22 @@ def patch_list(cmd, resource_group_name, managed_env, show_all=False):
else:
results[checkResult["id"]] = checkResult
else:
results["NotPatchable"].append(dict(targetContainerName=bom["targetContainerName"], targetContainerAppName=bom["targetContainerAppName"], revisionMode=bom["revisionMode"], targetImageName=bom["image_name"], oldRunImage=bom["remote_info"]["run_images"]["name"], newRunImage=None, id=None, reason=failedReason))
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["NotPatchable"].append(dict(targetContainerName=bom["targetContainerName"], targetContainerAppName=bom["targetContainerAppName"], revisionMode=bom["revisionMode"], targetImageName=bom["image_name"], oldRunImage=bom["remote_info"]["run_images"]["name"], newRunImage=None, id=None, reason=mcrCheckReason))
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 = {k: v for k, v in results.items() if k != "NotPatchable"}
return results

def patch_run(cmd, resource_group_name, managed_env, show_all=False):
def patch_run(cmd, resource_group_name, 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"]:
print("No patchable image found.")
if not show_all:
print("Use --show-all to show all the images' patchable check.")
print("Use --show-all to show all the patchable and unpatchable images.")
return
else:
patchable_check_results_json = json.dumps(patchable_check_results, indent=4)
Expand All @@ -4410,7 +4420,7 @@ def patch_apply(cmd, patchCheckList, method, resource_group_name):
patchCheckList[key]["newRunImage"],
patchCheckList[key]["revisionMode"]))
elif m == "n":
print("No patch applied.")
print("No patch applied."); return
else:
if method in patchCheckList.keys():
results.append(patch_cli_call(cmd,
Expand All @@ -4421,7 +4431,7 @@ def patch_apply(cmd, patchCheckList, method, resource_group_name):
patchCheckList[method]["newRunImage"],
patchCheckList[method]["revisionMode"]))
else:
print("Invalid patch method or id.")
print("Invalid patch method or id."); return
return results

def patch_cli_call(cmd, resource_group, container_app_name, container_name, target_image_name, new_run_image, revision_mode):
Expand Down Expand Up @@ -4450,4 +4460,3 @@ def patch_cli_call(cmd, resource_group, container_app_name, container_name, targ
except Exception:
print("Error: Failed to create new revision with the container app.")
raise

0 comments on commit a4c81ae

Please sign in to comment.