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

Container App Test suite #67

Merged
merged 3 commits into from
Apr 15, 2022
Merged
Changes from 2 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,202 @@
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")
class ContainerappScenarioTest(ScenarioTest):
@unittest.skip('Split into multiple tests that share the same ContainerApp Environment')
@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),
])

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)
])

# Subscriptions are limited to only a few environments, so just create one that can be shared by all Container Apps in this test class
def create_environment(self):
self.env_name = self.create_random_name(prefix='containerapp-e2e-env', length=24)
self.env_rg = self.create_random_name(prefix='containerapp-e2e-env', length=24)

self.cmd('group create -g {} -l centraluseuap'.format(self.env_rg))
self.cmd('containerapp env create -g {} -n {}'.format(self.env_rg, self.env_name))

# Ensure environment is completed
containerapp_env = self.cmd('containerapp env show -g {} -n {}'.format(self.env_rg, self.env_name)).get_output_in_json()
self.env_id = containerapp_env["id"]
while containerapp_env["properties"]["provisioningState"].lower() == "waiting":
time.sleep(5)
containerapp_env = self.cmd('containerapp env show -g {} -n {}'.format(self.env_rg, self.env_name))

def containerapp_e2e(self):
containerapp_name = self.create_random_name(prefix='containerapp-e2e', length=24)

self.cmd('containerapp env list -g {}'.format(self.env_rg), checks=[
JMESPathCheck('length(@)', 1),
JMESPathCheck('[0].name', self.env_name)
])

# Create basic Container App with default image
self.cmd('containerapp create -g {} -n {} --environment {}'.format(resource_group, containerapp_name, self.env_id), checks=[
JMESPathCheck('name', containerapp_name)
])

self.cmd('containerapp show -g {} -n {}'.format(resource_group, containerapp_name), checks=[
JMESPathCheck('name', containerapp_name),
])

self.cmd('containerapp list -g {}'.format(resource_group), checks=[
JMESPathCheck('length(@)', 1),
JMESPathCheck('[0].name', containerapp_name),
])

def containerapp_e2e_image(self):
containerapp_name = self.create_random_name(prefix='containerapp-e2e', length=24)

# 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, self.env_id)
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')
])

def containerapp_e2e_ingress(self):
containerapp_name = self.create_random_name(prefix='containerapp-e2e', length=24)

self.cmd('containerapp create -g {} -n {} --environment {} --ingress external --target-port 8080'.format(resource_group, containerapp_name, self.env_id), 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, self.env_id))

def containerapp_e2e_secrets(self):
containerapp_name = self.create_random_name(prefix='containerapp-e2e', length=24)

# Create Container App with secrets and environment variables
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, self.env_id)
self.cmd(create_string, checks=[
JMESPathCheck('name', containerapp_name),
JMESPathCheck('length(properties.template.containers[0].env)', 2),
JMESPathCheck('length(properties.configuration.secrets)', 2)
])

def containerapp_registry(self):
containerapp_name = self.create_random_name(prefix='containerapp-registry', length=24)
calvinsID marked this conversation as resolved.
Show resolved Hide resolved
registry_name = self.create_random_name(prefix='containerappregistry', length=24)

self.cmd('containerapp env list -g {}'.format(self.env_rg), checks=[
JMESPathCheck('length(@)', 1),
JMESPathCheck('[0].name', self.env_name)
])

# 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
create_string = 'containerapp create -g {} -n {} --environment {} --registry-username {} --registry-server {} --registry-password {}'.format(
resource_group, containerapp_name, self.env_id, 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('properties.configuration.registries[0].passwordSecretRef', 'properties.configuration.secrets[0].name'),
])

self.cmd('containerapp delete -g {} -n {}'.format(resource_group, containerapp_name))

self.cmd('containerapp list -g {}'.format(resource_group), checks=[
JMESPathCheck('length(@)', 0),
])

def containerapp_update(self):
containerapp_name = self.create_random_name(prefix='containerapp-update', length=24)

self.cmd('containerapp env list -g {}'.format(self.env_rg), checks=[
JMESPathCheck('length(@)', 1),
JMESPathCheck('[0].name', self.env_name)
])

# Create basic Container App with default image
self.cmd('containerapp create -g {} -n {} --environment {}'.format(resource_group, containerapp_name, self.env_id), checks=[
JMESPathCheck('name', containerapp_name),
JMESPathCheck('length(template.containers)', 1),
JMESPathCheck('template.containers[0].name', containerapp_name)
])

# Update existing Container App that has a single container
update_string = 'containerapp update -g {} -n {} --image {} --cpu {} --memory {} --args {} --command {} --revision-suffix {} --min-replicas {} --max-replicas {}'.format(
resource_group, containerapp_name, 'nginx', '0.5', '1.0Gi', '\"-c\" \"mycommand\"', '\"mycommand\"' 'suffix', '2', '4')
self.cmd(update_string, checks=[
JMESPathCheck('name', containerapp_name),
JMESPathCheck('length(template.containers)', 1),
JMESPathCheck('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),
JMESPathCheck('properties.latestRevisionName[:5]', 'suffix')
])

# 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(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'),
])

self.cmd('containerapp delete -g {} -n {}'.format(resource_group, containerapp_name))

self.cmd('containerapp list -g {}'.format(resource_group), checks=[
JMESPathCheck('length(@)', 0),
])

def clean_environment(self):
self.cmd('group delete -g {} --yes'.format(self.env_rg))

create_environment(self)
containerapp_e2e(self)
containerapp_e2e_image(self)
containerapp_e2e_ingress(self)
containerapp_e2e_secrets(self)
containerapp_registry(self)
containerapp_update(self)
containerapp_yaml(self)
calvinsID marked this conversation as resolved.
Show resolved Hide resolved
clean_environment(self)
calvinsID marked this conversation as resolved.
Show resolved Hide resolved