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

containerapp-preview support connected env command group #6527

Closed
Show file tree
Hide file tree
Changes from all 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
@@ -0,0 +1,40 @@
# coding=utf-8
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
from azure.cli.core.commands.client_factory import get_mgmt_service_client
from azure.cli.core.profiles import ResourceType


def _get_azext_containerapp_client_factory():
# avoid circular import
from ._utils import (_get_azext_containerapp_module)
return _get_azext_containerapp_module("azext_containerapp._client_factory")


def ex_handler_factory(no_throw=False):
return _get_azext_containerapp_client_factory().ex_handler_factory(no_throw)


def handle_raw_exception(e):
return _get_azext_containerapp_client_factory().handle_raw_exception(e)


def providers_client_factory(cli_ctx, subscription_id=None):
return get_mgmt_service_client(cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES, subscription_id=subscription_id).providers


def customlocation_client_factory(cli_ctx, api_version=None, subscription_id=None, **_):
from azure.cli.core.profiles import ResourceType
from azure.cli.core.commands.client_factory import get_mgmt_service_client

return get_mgmt_service_client(cli_ctx, ResourceType.MGMT_CUSTOMLOCATION, api_version=api_version,
subscription_id=subscription_id).custom_locations


def k8s_extension_client_factory(cli_ctx, subscription_id=None):
from azure.mgmt.kubernetesconfiguration import SourceControlConfigurationClient

r = get_mgmt_service_client(cli_ctx, SourceControlConfigurationClient, subscription_id=subscription_id)
return r.extensions
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
CONNECTED_ENVIRONMENT_TYPE = "connected"
MANAGED_ENVIRONMENT_RESOURCE_TYPE = "managedEnvironments"
CONNECTED_ENVIRONMENT_RESOURCE_TYPE = "connectedEnvironments"
CUSTOM_LOCATION_RESOURCE_TYPE = "customLocations"
GA_CONTAINERAPP_EXTENSION_NAME = 'containerapp'
MIN_GA_VERSION = '0.3.36'
CONTAINER_APPS_RP = "Microsoft.App"
EXTENDED_LOCATION_RP = "Microsoft.ExtendedLocation"
CONTAINER_APP_EXTENSION_TYPE = "microsoft.app.environment"
47 changes: 47 additions & 0 deletions src/containerapp-preview/azext_containerapp_preview/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,50 @@
--image my-app:v1.0 --environment MyContainerappConnectedEnv \\
--environment-type connected
"""

# Connected Environment Commands
helps['containerapp connected-env'] = """
type: group
short-summary: Commands to manage Container Apps Connected environments for use with Arc enabled Container Apps.
"""

helps['containerapp connected-env create'] = """
type: command
short-summary: Create a Container Apps connected environment.
long-summary: Create a Container Apps Connected environment for use with Arc enabled Container Apps. Environments are an isolation boundary around a collection of container apps.
examples:
- name: Create a connected environment
text: |
az containerapp connected-env create -n MyContainerappConnectedEnv -g MyResourceGroup \\
--location northcentralusstage --custom-location MyCustomLocationResourceID
"""


helps['containerapp connected-env delete'] = """
type: command
short-summary: Delete a Container Apps connected environment.
examples:
- name: Delete a connected environment.
text: az containerapp connected-env delete -n MyContainerappConnectedEnv -g MyResourceGroup
"""

helps['containerapp connected-env show'] = """
type: command
short-summary: Show details of a Container Apps connected environment.
examples:
- name: Show the details of a connected environment.
text: |
az containerapp connected-env show -n MyContainerappConnectedEnv -g MyResourceGroup
"""

helps['containerapp connected-env list'] = """
type: command
short-summary: List Container Apps connected environments by subscription or resource group.
examples:
- name: List connected environments in the current subscription.
text: |
az containerapp connected-env list
- name: List connected environments by resource group.
text: |
az containerapp connected-env list -g MyResourceGroup
"""
21 changes: 21 additions & 0 deletions src/containerapp-preview/azext_containerapp_preview/_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# coding=utf-8
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------


ConnectedEnvironment = {
"extendedLocation": None,
"tags": None,
"location": None,
"properties": {
"staticIp": None,
"daprAIConnectionString": None
}
}

ExtendedLocation = {
"name": None,
"type": None
}
22 changes: 20 additions & 2 deletions src/containerapp-preview/azext_containerapp_preview/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
# pylint: disable=line-too-long
from azure.cli.core.commands.parameters import get_enum_type
from azure.cli.core.commands.parameters import (get_enum_type,
get_location_type,
name_type,
resource_group_name_type,
tags_type)

from ._validators import validate_env_name_or_id
from ._validators import (validate_env_name_or_id,
validate_custom_location_name_or_id)


# This method cannot directly rely on GA resources.
Expand All @@ -16,3 +21,16 @@ def load_arguments(self, _):
with self.argument_context('containerapp create') as c:
c.argument('managed_env', validator=validate_env_name_or_id, options_list=['--environment'], help="Name or resource ID of the container app's environment.")
c.argument('environment_type', arg_type=get_enum_type(["managed", "connected"]), help="Type of environment.", is_preview=True)

with self.argument_context('containerapp connected-env', is_preview=True) as c:
c.argument('name', name_type, help='Name of the Container Apps environment.')
c.argument('resource_group_name', arg_type=resource_group_name_type)
c.argument('location', arg_type=get_location_type(self.cli_ctx), help='Location of resource. Examples: eastus2, northeurope')
c.argument('tags', arg_type=tags_type)
c.argument('custom_location', help="Resource ID of custom location. List using 'az customlocation list'.", validator=validate_custom_location_name_or_id)

with self.argument_context('containerapp connected-env', arg_group='Dapr', is_preview=True) as c:
c.argument('dapr_ai_connection_string', options_list=['--dapr-ai-connection-string', '--dapr-connection'], help='Connection string used for Dapr application insights.')

with self.argument_context('containerapp connected-env', arg_group='Network', is_preview=True) as c:
c.argument('static_ip', help='Static IP value.')
35 changes: 33 additions & 2 deletions src/containerapp-preview/azext_containerapp_preview/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
# --------------------------------------------------------------------------------------------
# pylint: disable=line-too-long

from azure.cli.core.azclierror import NoTTYError, ValidationError
from azure.cli.core.azclierror import ValidationError
from knack.util import CLIError
from knack.log import get_logger
from msrestazure.tools import parse_resource_id

from ._constants import MIN_GA_VERSION, GA_CONTAINERAPP_EXTENSION_NAME

from ._client_factory import (k8s_extension_client_factory, customlocation_client_factory)
logger = get_logger(__name__)


Expand Down Expand Up @@ -41,3 +42,33 @@ def _get_azext_containerapp_module(module_name):
return azext_custom
except ImportError as ie:
raise CLIError(ie) from ie


def get_cluster_extension(cmd, cluster_extension_id=None):
parsed_extension = parse_resource_id(cluster_extension_id)
subscription_id = parsed_extension.get("subscription")
cluster_rg = parsed_extension.get("resource_group")
cluster_rp = parsed_extension.get("namespace")
cluster_type = parsed_extension.get("type")
cluster_name = parsed_extension.get("name")
resource_name = parsed_extension.get("resource_name")

return k8s_extension_client_factory(cmd.cli_ctx, subscription_id=subscription_id).get(
resource_group_name=cluster_rg,
cluster_rp=cluster_rp,
cluster_resource_name=cluster_type,
cluster_name=cluster_name,
extension_name=resource_name)


def get_custom_location(cmd, custom_location_id):
parsed_custom_loc = parse_resource_id(custom_location_id)
subscription_id = parsed_custom_loc.get("subscription")
custom_loc_name = parsed_custom_loc["name"]
custom_loc_rg = parsed_custom_loc["resource_group"]
custom_location = None
try:
custom_location = customlocation_client_factory(cmd.cli_ctx, subscription_id=subscription_id).get(resource_group_name=custom_loc_rg, resource_name=custom_loc_name)
except:
pass
return custom_location
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
CONNECTED_ENVIRONMENT_TYPE,
MANAGED_ENVIRONMENT_RESOURCE_TYPE,
CONNECTED_ENVIRONMENT_RESOURCE_TYPE,
CONTAINER_APPS_RP)
CONTAINER_APPS_RP,
CUSTOM_LOCATION_RESOURCE_TYPE,
EXTENDED_LOCATION_RP)


def validate_env_name_or_id(cmd, namespace):
Expand Down Expand Up @@ -50,3 +52,20 @@ def validate_env_name_or_id(cmd, namespace):
type=MANAGED_ENVIRONMENT_RESOURCE_TYPE,
name=namespace.managed_env
)


def validate_custom_location_name_or_id(cmd, namespace):
from azure.cli.core.commands.client_factory import get_subscription_id
from msrestazure.tools import is_valid_resource_id, resource_id

if not namespace.custom_location or not namespace.resource_group_name:
return

if not is_valid_resource_id(namespace.custom_location):
namespace.custom_location = resource_id(
subscription=get_subscription_id(cmd.cli_ctx),
resource_group=namespace.resource_group_name,
namespace=EXTENDED_LOCATION_RP,
type=CUSTOM_LOCATION_RESOURCE_TYPE,
name=namespace.custom_location
)
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ def load_command_table(self, _):
g.custom_command('list', 'list_containerapp', table_transformer=transform_containerapp_list_output, is_preview=True)
g.custom_command('delete', 'delete_containerapp', supports_no_wait=True, confirmation=True, exception_handler=ex_handler_factory(), is_preview=True)
g.custom_command('create', 'create_containerapp', supports_no_wait=True, exception_handler=ex_handler_factory(), table_transformer=transform_containerapp_output, is_preview=True)

with self.command_group('containerapp connected-env', is_preview=True) as g:
g.custom_show_command('show', 'show_connected_environment')
g.custom_command('list', 'list_connected_environments')
g.custom_command('create', 'create_connected_environment', supports_no_wait=True, exception_handler=ex_handler_factory())
g.custom_command('delete', 'delete_connected_environment', supports_no_wait=True, confirmation=True, exception_handler=ex_handler_factory())
Loading