Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 6 additions & 1 deletion src/containerapp-compose/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@ Release History

0.1.0
++++++
* Initial release.
* Initial release.

0.2.0
++++++
* Add basic build support
* Fix bug in specifying memory
100 changes: 54 additions & 46 deletions src/containerapp-compose/azext_containerapp_compose/_monkey_patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import sys

from knack.log import get_logger
from azure.cli.core.azclierror import AzCLIError

Expand All @@ -16,44 +14,6 @@ def __init__(self, error_msg) -> None:
super().__init__(error_msg, recommendation)


def uncache(exclude):
pkgs = []
for mod in exclude:
pkg = mod.split('.', 1)[0]
pkgs.append(pkg)
to_uncache = []
for mod in sys.modules:
if mod in exclude:
continue
if mod in pkgs:
to_uncache.append(mod)
continue
for pkg in pkgs:
if mod.startswith(pkg + '.'):
to_uncache.append(mod)
break
for mod in to_uncache:
del sys.modules[mod]


# Monkey patch for the PollingAnimation
# removes the spinner and message written to standard out
# which breaks the ability to re-use output from the
# the containerapp compose create command
# example:
# `URL=$(az containerapp compose create -e myenv -g myrg --query [0].properties.configuration.ingress.fqdn -o tsv)`
# In that example, the URL variable would include a number of lines with the polling animation,
# making it difficult to reusue the output from the CLI command.
def tick(self):
self.currTicker += 1
self.currTicker = self.currTicker % len(self.tickers)


# Monkey patch for the PollingAnimation (see above)
def flush(self): # noqa: W0613 pylint: disable=unused-argument
pass


logger = get_logger(__name__)


Expand All @@ -65,12 +25,14 @@ def log_containerapp_extension_required():


try:
from azext_containerapp import custom # pylint: disable=unused-import
from azext_containerapp import _utils # pylint: disable=unused-import
from azext_containerapp import _clients # pylint: disable=unused-import
_clients.PollingAnimation.tick = tick
_clients.PollingAnimation.flush = flush
uncache("azext_containerapp._clients")
from azext_containerapp import custom
from azext_containerapp import _utils
from azext_containerapp._up_utils import (ContainerApp,
ContainerAppEnvironment,
ResourceGroup,
_get_registry_from_app,
_get_registry_details,
) # pylint: disable=unused-import
from azext_containerapp import _clients # pylint: disable=unused-import
from azext_containerapp._clients import ManagedEnvironmentClient # pylint: disable=unused-import
except ModuleNotFoundError:
Expand Down Expand Up @@ -101,6 +63,52 @@ def create_containerapps_compose_environment(cmd,
tags=tags)


def build_containerapp_from_compose_service(cmd,
name,
source,
dockerfile,
resource_group_name,
managed_env,
location,
image,
target_port,
ingress,
registry_server,
registry_user,
registry_pass,
env_vars,
logs_key=None,
logs_customer_id=None):

resource_group = ResourceGroup(cmd, name=resource_group_name, location=location)
env = ContainerAppEnvironment(cmd,
managed_env,
resource_group,
location=location,
logs_key=logs_key,
logs_customer_id=logs_customer_id)
app = ContainerApp(cmd,
name,
resource_group,
None,
image,
env,
target_port,
registry_server,
registry_user,
registry_pass,
env_vars,
ingress)

if not registry_server:
_get_registry_from_app(app, True) # if the app exists, get the registry
_get_registry_details(cmd, app, True) # fetch ACR creds from arguments registry arguments

app.create_acr_if_needed()
app.run_acr_build(dockerfile, source, False)
return app.image, app.registry_server, app.registry_user, app.registry_pass


def create_containerapp_from_service(*args, **kwargs):
return custom.create_containerapp(*args, **kwargs)

Expand Down
44 changes: 39 additions & 5 deletions src/containerapp-compose/azext_containerapp_compose/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
logger = get_logger(__name__)


def resolve_configuration_element_list(compose_service, unsupported_configuration):
def resolve_configuration_element_list(compose_service, unsupported_configuration, area=None):
if area is not None:
compose_service = getattr(compose_service, area)
config_list = []
for configuration_element in unsupported_configuration:
try:
Expand All @@ -27,11 +29,18 @@ def resolve_configuration_element_list(compose_service, unsupported_configuratio


def warn_about_unsupported_build_configuration(compose_service):
unsupported_configuration = ["args", "ssh", "cache_from", "cache_to", "extra_hosts",
"isolation", "labels", "no_cache", "pull", "shm_size",
"target", "secrets", "tags"]
if compose_service.build is not None:
message = f"Build configuration for {compose_service.build.compose_path} is not currently supported."
message += " Work is planned to add that capability."
config_list = resolve_configuration_element_list(compose_service, unsupported_configuration, 'build')
message = "These build configuration settings from the docker-compose file are yet supported."
message += " Currently, we support supplying a build context and optionally target Dockerfile for a service."
message += " See https://aka.ms/containerapp/compose/build_support for more information or to add feedback."
logger.warning(message)
if len(config_list) >= 1:
logger.warning(message)
for item in config_list:
logger.warning(" %s", item)


def warn_about_unsupported_runtime_host_configuration(compose_service):
Expand Down Expand Up @@ -110,6 +119,7 @@ def create_containerapps_from_compose(cmd, # pylint: disable=R0914
from ._monkey_patch import (
create_containerapp_from_service,
create_containerapps_compose_environment,
build_containerapp_from_compose_service,
load_yaml_file,
show_managed_environment)

Expand Down Expand Up @@ -142,6 +152,7 @@ def create_containerapps_from_compose(cmd, # pylint: disable=R0914
message = "Unsupported platform found. "
message += "Azure Container Apps only supports linux/amd64 container images."
raise InvalidArgumentValueError(message)
image = service.image
warn_about_unsupported_elements(service)
logger.info( # pylint: disable=W1203
f"Creating the Container Apps instance for {service_name} under {resource_group_name} in {location}.")
Expand All @@ -161,11 +172,34 @@ def create_containerapps_from_compose(cmd, # pylint: disable=R0914
elif secret_env_ref is not None:
environment = secret_env_ref

if service.build is not None:
logger.warning("Build configuration defined for this service.")
logger.warning("The build will be performed by Azure Container Registry.")
context = service.build.context
dockerfile = "Dockerfile"
if service.build.dockerfile is not None:
dockerfile = service.build.dockerfile
image, registry, registry_username, registry_password = build_containerapp_from_compose_service(
cmd,
service_name,
context,
dockerfile,
resource_group_name,
managed_env,
location,
image,
target_port,
ingress_type,
registry,
registry_username,
registry_password,
environment)

containerapps_from_compose.append(
create_containerapp_from_service(cmd,
service_name,
resource_group_name,
image=service.image,
image=image,
container_name=service.container_name,
managed_env=managed_environment["id"],
ingress=ingress_type,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ def clean_up_test_file(filename):

class ContainerappComposePreviewScenarioTest(ScenarioTest):
def setUp(self):
self.cmd("extension add --name containerapp")
self.cmd("extension add --name containerapp --upgrade --yes")
return super().setUp()
4 changes: 2 additions & 2 deletions src/containerapp-compose/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

# TODO: Confirm this is the right version number you want and it matches your
# HISTORY.rst entry.
VERSION = '0.1.0'
VERSION = '0.2.0'

# The full list of classifiers is available at
# https://pypi.python.org/pypi?%3Aaction=list_classifiers
Expand All @@ -32,7 +32,7 @@
'License :: OSI Approved :: MIT License',
]

DEPENDENCIES = ['pycomposefile>=0.0.26']
DEPENDENCIES = ['pycomposefile>=0.0.29']

with open('README.rst', 'r', encoding='utf-8') as f:
README = f.read()
Expand Down