Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

P1s #43

Merged
merged 88 commits into from
Apr 6, 2022
Merged

P1s #43

Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
a8eb7d7
Skeleton code
calvinsID Feb 3, 2022
c2963ce
az containerapp env show
calvinsID Feb 3, 2022
e461384
List kube/managed environments
calvinsID Feb 3, 2022
b5e9381
Create kube environment, wait doesn't work yet
calvinsID Feb 4, 2022
23ca42f
Update containerapp stubs (check if it is supported now)
calvinsID Feb 4, 2022
919ed4e
Containerapp env delete, polling not working yet
calvinsID Feb 4, 2022
f1d2d0c
Added polling for create and delete
calvinsID Feb 4, 2022
22ecb09
Use Microsoft.App RP for show, list, delete command
calvinsID Feb 5, 2022
e756d4e
Create containerapp env using Microsoft.App RP
calvinsID Feb 6, 2022
3392755
Add optional containerapp env create arguments
calvinsID Feb 8, 2022
ef13ece
Remove old kube environment code, naming fixes
calvinsID Feb 8, 2022
eeb4c8b
Containerapp create almost done
calvinsID Feb 11, 2022
12cf40c
Done containerapp create, except for --yaml. Need to test
calvinsID Feb 11, 2022
509b91c
Containerapp show, list
calvinsID Feb 11, 2022
e60ad9d
Fix helptext
calvinsID Feb 11, 2022
b99c054
Containerapp delete
calvinsID Feb 11, 2022
f538a24
Containerapp update. Needs secrets api to be implemented, and testing
calvinsID Feb 14, 2022
25e8e1a
Add scale command
calvinsID Feb 14, 2022
4cce2e8
Various validations, small fixes
calvinsID Feb 15, 2022
074e1ad
listSecrets API for updates, autogen log analytics for env
calvinsID Feb 18, 2022
e1f2bfc
Use space delimiter for secrets and env variables
calvinsID Feb 24, 2022
8d36f9a
Verify sub is registered to Microsoft.ContainerRegistration if creati…
calvinsID Feb 25, 2022
725a841
Containerapp create --yaml
calvinsID Feb 23, 2022
f6479f1
Fix updating registry to do create or update
calvinsID Feb 23, 2022
c98d02c
Fix containerapp update command. Add image-name parameter to support …
calvinsID Feb 23, 2022
b581786
started update with --yaml. Need to do create or update for when an a…
calvinsID Feb 23, 2022
1a8b598
use space delimiter for startup_command and args, instead of comma de…
calvinsID Feb 24, 2022
51be4de
Traffic weights
calvinsID Mar 1, 2022
1b3bb9c
List and show revisions
calvinsID Feb 24, 2022
00602b6
az containerapp revision restart, activate, deactivate
calvinsID Feb 24, 2022
d034188
Add ability for users to clear args/command in az containerapp update
calvinsID Mar 3, 2022
788bb3f
Various fixes, traffic weights fixes
calvinsID Mar 3, 2022
a5acf07
Verify subnet subscription is registered to Microsoft.ContainerServices
calvinsID Mar 4, 2022
9b66d17
GitHub Actions Update (#17)
runefa Mar 8, 2022
a12c86d
Remove --location since location must be same as managed env
calvinsID Mar 8, 2022
d561c46
Add options for flag names: --env-vars and --registry-srever
calvinsID Mar 8, 2022
dd3d799
Empty string to clear env_vars
calvinsID Mar 8, 2022
ea87b77
Default revisions_mode to single
calvinsID Mar 8, 2022
44edebb
Infer acr credentials if it is acr and credentials are not provided
calvinsID Mar 8, 2022
6ae589c
fix help msg
calvinsID Mar 8, 2022
47e49f3
if image is hosted on acr, and no registry server is supplied, infer …
calvinsID Mar 9, 2022
5b58d6f
Added subgroups (Ingress, Registry, Secret) and updated revisions (#18)
runefa Mar 11, 2022
3fa18df
More p0 fixes (#20)
calvinsID Mar 11, 2022
c72c29e
Update help text (#21)
anthonychu Mar 14, 2022
c09fe39
New 1.0.1 version
calvinsID Mar 14, 2022
d264bbf
Added identity commands + --assign-identity flag to containerapp crea…
runefa Mar 14, 2022
77c742d
Dapr Commands (#23)
runefa Mar 14, 2022
3394781
Rename --image-name to --container-name
calvinsID Mar 14, 2022
d406c0b
Remove allowInsecure since it was messing with the api parsing
calvinsID Mar 14, 2022
551ea0d
Fix for env var being empty string
calvinsID Mar 14, 2022
f7cd94d
Rename to --dapr-instrumentation-key, only infer ACR credentials if -…
calvinsID Mar 14, 2022
fa4be8a
Remove az containerapp scale
calvinsID Mar 14, 2022
e5ddac4
Fix delete containerapp errors
calvinsID Mar 14, 2022
b0c6f95
Remove ingress, dapr flags from az containerapp update/revision copy
calvinsID Mar 14, 2022
8e30e91
Fix revision list -o table
calvinsID Mar 14, 2022
013507f
Help text fix
calvinsID Mar 14, 2022
32ed50b
Bump extension to 0.1.2
calvinsID Mar 14, 2022
5c99446
Update managed identities and Dapr help text (#25)
anthonychu Mar 15, 2022
ddc07c0
Env var options + various bug fixes (#26)
runefa Mar 16, 2022
5fe8e5f
Fixed style issues, various bug fixes (#27)
runefa Mar 18, 2022
87a6101
Update src/containerapp/azext_containerapp/tests/latest/test_containe…
runefa Mar 18, 2022
8f4b5c6
Specific Error Types + Bugfixes (Help, remove app-subnet-resource-id,…
runefa Mar 21, 2022
6f135aa
Reset to 0.1.0 version, remove unneeded options-list
calvinsID Mar 21, 2022
1977e33
Update min cli core version
calvinsID Mar 21, 2022
c7ed3ca
Fixed style issues. (#30)
runefa Mar 21, 2022
35017f1
Fix linter issues
calvinsID Mar 21, 2022
cf0345e
Use custom-show-command
calvinsID Mar 21, 2022
bddcd61
Removed --ids from revision, secret, registry list.
Mar 21, 2022
9a1354f
Add linter exclusions
calvinsID Mar 21, 2022
a375593
Fix polling on delete containerapp
calvinsID Mar 21, 2022
956875c
Fix error handling
calvinsID Mar 21, 2022
7606bae
Add Container App Service
calvinsID Mar 21, 2022
7ceb9c3
Fix flake linter
calvinsID Mar 21, 2022
9683a85
Fix help text
calvinsID Mar 22, 2022
19b808a
Mark extension as preview
calvinsID Mar 22, 2022
0c2318b
Add python 3.9 and 3.10 as supported
calvinsID Mar 22, 2022
de4b8a8
Remove registries and secrets from az containerapp update, in favor o…
calvinsID Mar 22, 2022
ef0cbc1
Fix YAML not working
calvinsID Mar 22, 2022
943cafd
Move import to inside deserialize function
calvinsID Mar 22, 2022
51bc543
Ingress enable --transport default. Secret list returns empty array. …
Mar 22, 2022
37030ad
Fixed dapr in create.
Mar 23, 2022
60f9e4b
Revert "Ingress enable --transport default. Secret list returns empty…
Mar 23, 2022
feb12a7
Revert "Fixed dapr in create."
Mar 23, 2022
e639c00
Ingress enable --transport default. Secret list returns empty array. …
Mar 22, 2022
1798852
Reduced redundant code between revision copy and containerapp update.
Mar 24, 2022
501756a
Merged containerapp.
Mar 24, 2022
a06d619
Fixed merge issues.
Mar 24, 2022
636d3f7
Fixed merge conflicts, moved helper function
Mar 24, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
301 changes: 105 additions & 196 deletions src/containerapp/azext_containerapp/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,33 +456,34 @@ 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:
if image or min_replicas or max_replicas or\
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:
Expand All @@ -493,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"]:
Expand Down Expand Up @@ -640,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")

Expand Down Expand Up @@ -1222,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):
Expand Down Expand Up @@ -1437,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
Expand Down Expand Up @@ -1715,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):
Expand Down Expand Up @@ -1823,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)
Expand Down