-
Notifications
You must be signed in to change notification settings - Fork 1.5k
ContainerApps 04/19 Release #4689
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
Changes from 14 commits
1de51ee
7735595
2e1be89
5fcd785
a1929c8
df5cc99
0dedf19
1474d69
5afc2b1
77dcaa0
5cc0aa8
1f1b31a
7f70e2f
fa539a8
f935df8
7da2e9a
fcc3d87
cb6820e
f6efbd2
4e805bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -527,7 +527,7 @@ class GitHubActionClient(): | |
| @classmethod | ||
| def create_or_update(cls, cmd, resource_group_name, name, github_action_envelope, headers, no_wait=False): | ||
| management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager | ||
| api_version = NEW_API_VERSION | ||
| api_version = "2022-03-01" | ||
|
||
| sub_id = get_subscription_id(cmd.cli_ctx) | ||
| url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/sourcecontrols/current?api-version={}" | ||
| request_url = url_fmt.format( | ||
|
|
@@ -556,7 +556,7 @@ def create_or_update(cls, cmd, resource_group_name, name, github_action_envelope | |
| @classmethod | ||
| def show(cls, cmd, resource_group_name, name): | ||
| management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager | ||
| api_version = NEW_API_VERSION | ||
| api_version = "2022-03-01" | ||
|
||
| sub_id = get_subscription_id(cmd.cli_ctx) | ||
| url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/sourcecontrols/current?api-version={}" | ||
| request_url = url_fmt.format( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,35 +8,176 @@ | |
| import unittest | ||
|
|
||
| from azure.cli.testsdk.scenario_tests import AllowLargeResponse | ||
| from azure.cli.testsdk import (ScenarioTest, ResourceGroupPreparer, JMESPathCheck) | ||
| from azure.cli.testsdk import (ScenarioTest, ResourceGroupPreparer, JMESPathCheck, live_only) | ||
| from knack.util import CLIError | ||
|
|
||
|
|
||
| TEST_DIR = os.path.abspath(os.path.join(os.path.abspath(__file__), '..')) | ||
|
|
||
|
|
||
| @unittest.skip("Managed environment flaky") | ||
| @live_only() | ||
| class ContainerappScenarioTest(ScenarioTest): | ||
| @AllowLargeResponse(8192) | ||
| @ResourceGroupPreparer(location="centraluseuap") | ||
|
||
| def test_containerapp_e2e(self, resource_group): | ||
| containerapp_name = self.create_random_name(prefix='containerapp-e2e', length=24) | ||
| env_name = self.create_random_name(prefix='containerapp-e2e-env', length=24) | ||
|
|
||
| self.cmd('containerapp env create -g {} -n {}'.format(resource_group, env_name)) | ||
|
|
||
| # Sleep in case env create takes a while | ||
| time.sleep(60) | ||
| self.cmd('containerapp env list -g {}'.format(resource_group), checks=[ | ||
| JMESPathCheck('length(@)', 1), | ||
| JMESPathCheck('[0].name', env_name), | ||
| ]) | ||
| # Ensure environment is completed | ||
| containerapp_env = self.cmd('containerapp env show -g {} -n {}'.format(resource_group, env_name)).get_output_in_json() | ||
|
|
||
| while containerapp_env["properties"]["provisioningState"].lower() == "waiting": | ||
| time.sleep(5) | ||
| containerapp_env = self.cmd('containerapp env show -g {} -n {}'.format(resource_group, env_name)).get_output_in_json() | ||
|
|
||
| containerapp_name = self.create_random_name(prefix='containerapp-e2e', length=24) | ||
|
|
||
| # Create basic Container App with default image | ||
| self.cmd('containerapp create -g {} -n {} --environment {}'.format(resource_group, containerapp_name, env_name), checks=[ | ||
| JMESPathCheck('name', containerapp_name) | ||
| ]) | ||
|
|
||
| # Sleep in case containerapp create takes a while | ||
| time.sleep(60) | ||
| self.cmd('containerapp show -g {} -n {}'.format(resource_group, containerapp_name), checks=[ | ||
| JMESPathCheck('name', containerapp_name) | ||
| JMESPathCheck('name', containerapp_name), | ||
| ]) | ||
|
|
||
| self.cmd('containerapp list -g {}'.format(resource_group), checks=[ | ||
| JMESPathCheck('length(@)', 1), | ||
| JMESPathCheck('[0].name', containerapp_name), | ||
| ]) | ||
|
|
||
| # Create Container App with image, resource and replica limits | ||
| create_string = "containerapp create -g {} -n {} --environment {} --image nginx --cpu 0.5 --memory 1.0Gi --min-replicas 2 --max-replicas 4".format(resource_group, containerapp_name, env_name) | ||
| self.cmd(create_string, checks=[ | ||
| JMESPathCheck('name', containerapp_name), | ||
| JMESPathCheck('properties.template.containers[0].image', 'nginx'), | ||
| JMESPathCheck('properties.template.containers[0].resources.cpu', '0.5'), | ||
| JMESPathCheck('properties.template.containers[0].resources.memory', '1Gi'), | ||
| JMESPathCheck('properties.template.scale.minReplicas', '2'), | ||
| JMESPathCheck('properties.template.scale.maxReplicas', '4') | ||
| ]) | ||
|
|
||
| self.cmd('containerapp create -g {} -n {} --environment {} --ingress external --target-port 8080'.format(resource_group, containerapp_name, env_name), checks=[ | ||
| JMESPathCheck('properties.configuration.ingress.external', True), | ||
| JMESPathCheck('properties.configuration.ingress.targetPort', 8080) | ||
| ]) | ||
|
|
||
| # Container App with ingress should fail unless target port is specified | ||
| with self.assertRaises(CLIError): | ||
| self.cmd('containerapp create -g {} -n {} --environment {} --ingress external'.format(resource_group, containerapp_name, env_name)) | ||
|
|
||
| # Create Container App with secrets and environment variables | ||
| containerapp_name = self.create_random_name(prefix='containerapp-e2e', length=24) | ||
| create_string = 'containerapp create -g {} -n {} --environment {} --secrets mysecret=secretvalue1 anothersecret="secret value 2" --env-vars GREETING="Hello, world" SECRETENV=secretref:anothersecret'.format( | ||
| resource_group, containerapp_name, env_name) | ||
| self.cmd(create_string, checks=[ | ||
| JMESPathCheck('name', containerapp_name), | ||
| JMESPathCheck('length(properties.template.containers[0].env)', 2), | ||
| JMESPathCheck('length(properties.configuration.secrets)', 2) | ||
| ]) | ||
|
|
||
|
|
||
| @AllowLargeResponse(8192) | ||
| @ResourceGroupPreparer(location="eastus2") | ||
| def test_container_acr(self, resource_group): | ||
| env_name = self.create_random_name(prefix='containerapp-e2e-env', length=24) | ||
|
|
||
| self.cmd('containerapp env create -g {} -n {}'.format(resource_group, env_name)) | ||
|
|
||
| # Ensure environment is completed | ||
| containerapp_env = self.cmd('containerapp env show -g {} -n {}'.format(resource_group, env_name)).get_output_in_json() | ||
|
|
||
| while containerapp_env["properties"]["provisioningState"].lower() == "waiting": | ||
| time.sleep(5) | ||
| containerapp_env = self.cmd('containerapp env show -g {} -n {}'.format(resource_group, env_name)).get_output_in_json() | ||
|
|
||
| containerapp_name = self.create_random_name(prefix='containerapp-e2e', length=24) | ||
| registry_name = self.create_random_name(prefix='containerapp', length=24) | ||
|
|
||
| # Create ACR | ||
| acr = self.cmd('acr create -g {} -n {} --sku Basic --admin-enabled'.format(resource_group, registry_name)).get_output_in_json() | ||
| registry_server = acr["loginServer"] | ||
|
|
||
| acr_credentials = self.cmd('acr credential show -g {} -n {}'.format(resource_group, registry_name)).get_output_in_json() | ||
| registry_username = acr_credentials["username"] | ||
| registry_password = acr_credentials["passwords"][0]["value"] | ||
|
|
||
| # Create Container App with ACR | ||
| containerapp_name = self.create_random_name(prefix='containerapp-e2e', length=24) | ||
| create_string = 'containerapp create -g {} -n {} --environment {} --registry-username {} --registry-server {} --registry-password {}'.format( | ||
| resource_group, containerapp_name, env_name, registry_username, registry_server, registry_password) | ||
| self.cmd(create_string, checks=[ | ||
| JMESPathCheck('name', containerapp_name), | ||
| JMESPathCheck('properties.configuration.registries[0].server', registry_server), | ||
| JMESPathCheck('properties.configuration.registries[0].username', registry_username), | ||
| JMESPathCheck('length(properties.configuration.secrets)', 1), | ||
| ]) | ||
|
|
||
|
|
||
| @AllowLargeResponse(8192) | ||
| @ResourceGroupPreparer(location="eastus") | ||
| def test_containerapp_update(self, resource_group): | ||
| env_name = self.create_random_name(prefix='containerapp-e2e-env', length=24) | ||
|
|
||
| self.cmd('containerapp env create -g {} -n {}'.format(resource_group, env_name)) | ||
|
|
||
| # Ensure environment is completed | ||
| containerapp_env = self.cmd('containerapp env show -g {} -n {}'.format(resource_group, env_name)).get_output_in_json() | ||
|
|
||
| while containerapp_env["properties"]["provisioningState"].lower() == "waiting": | ||
| time.sleep(5) | ||
| containerapp_env = self.cmd('containerapp env show -g {} -n {}'.format(resource_group, env_name)).get_output_in_json() | ||
|
|
||
| # Create basic Container App with default image | ||
| containerapp_name = self.create_random_name(prefix='containerapp-update', length=24) | ||
| self.cmd('containerapp create -g {} -n {} --environment {}'.format(resource_group, containerapp_name, env_name), checks=[ | ||
| JMESPathCheck('name', containerapp_name), | ||
| JMESPathCheck('length(properties.template.containers)', 1), | ||
| JMESPathCheck('properties.template.containers[0].name', containerapp_name) | ||
| ]) | ||
|
|
||
| # Update existing Container App that has a single container | ||
|
|
||
| update_string = 'containerapp update -g {} -n {} --image {} --cpu 0.5 --memory 1.0Gi --args mycommand mycommand2 --command "mycommand" --revision-suffix suffix --min-replicas 2 --max-replicas 4'.format( | ||
| resource_group, containerapp_name, 'nginx') | ||
| self.cmd(update_string, checks=[ | ||
| JMESPathCheck('name', containerapp_name), | ||
| JMESPathCheck('length(properties.template.containers)', 1), | ||
| JMESPathCheck('properties.template.containers[0].name', containerapp_name), | ||
| JMESPathCheck('properties.template.containers[0].image', 'nginx'), | ||
| JMESPathCheck('properties.template.containers[0].resources.cpu', '0.5'), | ||
| JMESPathCheck('properties.template.containers[0].resources.memory', '1Gi'), | ||
| JMESPathCheck('properties.template.scale.minReplicas', '2'), | ||
| JMESPathCheck('properties.template.scale.maxReplicas', '4'), | ||
| JMESPathCheck('properties.template.containers[0].command[0]', "mycommand"), | ||
| JMESPathCheck('length(properties.template.containers[0].args)', 2) | ||
| ]) | ||
|
|
||
| # Add new container to existing Container App | ||
| update_string = 'containerapp update -g {} -n {} --container-name {} --image {}'.format( | ||
| resource_group, containerapp_name, "newcontainer", "nginx") | ||
| self.cmd(update_string, checks=[ | ||
| JMESPathCheck('name', containerapp_name), | ||
| JMESPathCheck('length(properties.template.containers)', 2) | ||
| ]) | ||
|
|
||
| # Updating container properties in a Container App with multiple containers, without providing container name should error | ||
| update_string = 'containerapp update -g {} -n {} --cpu {} --memory {}'.format( | ||
| resource_group, containerapp_name, '1.0', '2.0Gi') | ||
| with self.assertRaises(CLIError): | ||
| self.cmd(update_string) | ||
|
|
||
| # Updating container properties in a Container App with multiple containers, should work when container name provided | ||
| update_string = 'containerapp update -g {} -n {} --container-name {} --cpu {} --memory {}'.format( | ||
| resource_group, containerapp_name, 'newcontainer', '0.75', '1.5Gi') | ||
| self.cmd(update_string) | ||
|
|
||
| update_string = 'containerapp update -g {} -n {} --container-name {} --cpu {} --memory {}'.format( | ||
| resource_group, containerapp_name, containerapp_name, '0.75', '1.5Gi') | ||
| self.cmd(update_string, checks=[ | ||
| JMESPathCheck('properties.template.containers[0].resources.cpu', '0.75'), | ||
| JMESPathCheck('properties.template.containers[0].resources.memory', '1.5Gi'), | ||
| JMESPathCheck('properties.template.containers[1].resources.cpu', '0.75'), | ||
| JMESPathCheck('properties.template.containers[1].resources.memory', '1.5Gi'), | ||
| ]) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets explicitly call out docker-path replaced by context-path
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just fixed this