Skip to content
1 change: 1 addition & 0 deletions src/containerapp/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ upcoming
* 'az containerapp up': support for `--kind` parameter
* 'az containerapp env premium-ingress': Deprecate `--min-replicas` and `--max-replicas` parameters, use workload profile scale instead.
* 'az containerapp sessionpool create/update': Support `--probe-yaml`
* 'az containerapp session stop': Support stop session for custom container sessions

1.2.0b3
++++++
Expand Down
17 changes: 17 additions & 0 deletions src/containerapp/azext_containerapp/_clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -1513,6 +1513,23 @@ def extract_path_from_filename(path, filename):
return path.rstrip("/") + "/" + path_in_filename.lstrip('/'), filename


class SessionCustomContainerPreviewClient():
# pylint: disable=too-few-public-methods
session_dp_api_version = "2025-02-02-preview" # may be different from ACA CP
Comment thread
ShichaoQiu marked this conversation as resolved.
Comment thread
ShichaoQiu marked this conversation as resolved.

@classmethod
def stop_session(cls, cmd, identifier, session_pool_endpoint):
Comment thread
ShichaoQiu marked this conversation as resolved.
url_fmt = "{}/.management/stopSession?identifier={}&api-version={}"
request_url = url_fmt.format(
session_pool_endpoint,
identifier,
cls.session_dp_api_version)

r = send_raw_request(cmd.cli_ctx, "POST", request_url, resource=SESSION_RESOURCE)
Comment thread
ShichaoQiu marked this conversation as resolved.

return r.text


class DotNetComponentPreviewClient():
api_version = PREVIEW_API_VERSION

Expand Down
12 changes: 11 additions & 1 deletion src/containerapp/azext_containerapp/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -2058,12 +2058,22 @@
az containerapp sessionpool list -g MyResourceGroup
"""

# code interpreter commands
# Session Commands
helps['containerapp session'] = """
type: group
short-summary: Commands to manage sessions.To learn more about individual commands under each subgroup run containerapp session [subgroup name] --help.
"""

helps['containerapp session stop'] = """
type: command
short-summary: Stop a custom container session.
examples:
- name: Stop a custom container session.
text: |
az containerapp session stop -n MySessionPool -g MyResourceGroup --identifier MySession
"""

# code interpreter commands
helps['containerapp session code-interpreter'] = """
type: group
short-summary: Commands to interact with and manage code interpreter sessions.
Expand Down
10 changes: 8 additions & 2 deletions src/containerapp/azext_containerapp/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -479,10 +479,16 @@ def load_arguments(self, _):
c.argument('registry_user', validator=validate_registry_user, options_list=['--registry-username'], help="The username to log in to container registry.")
c.argument('registry_identity', validator=validate_registry_user, help="The managed identity with which to authenticate to the Azure Container Registry (instead of username/password). Use 'system' for a system-assigned identity, use a resource ID for a user-assigned identity. The managed identity should have been assigned acrpull permissions on the ACR before deployment (use 'az role assignment create --role acrpull ...').")

# sessions code interpreter commands
with self.argument_context('containerapp session code-interpreter') as c:
# sessions commands
with self.argument_context('containerapp session') as c:
c.argument('name', options_list=['--name', '-n'], help="The Session Pool name.")
c.argument('resource_group_name', arg_type=resource_group_name_type, id_part=None)

with self.argument_context('containerapp session stop') as c:
c.argument('identifier', options_list=['--identifier', '-i'], help="The Session Identifier")

# sessions code interpreter commands
with self.argument_context('containerapp session code-interpreter') as c:
c.argument('identifier', options_list=['--identifier', '-i'], help="The Session Identifier")
c.argument('session_pool_location', help="The location of the session pool")

Expand Down
3 changes: 3 additions & 0 deletions src/containerapp/azext_containerapp/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ def load_command_table(self, args):
g.custom_command('update', 'update_session_pool', supports_no_wait=True)
g.custom_command('delete', 'delete_session_pool', confirmation=True, supports_no_wait=True)

with self.command_group('containerapp session') as g:
g.custom_command('stop', 'stop_session_custom_container', is_preview=True)

with self.command_group('containerapp session code-interpreter') as g:
g.custom_command('execute', 'execute_session_code_interpreter', supports_no_wait=True)
g.custom_command('upload-file', 'upload_session_code_interpreter', supports_no_wait=True)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# 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.
# --------------------------------------------------------------------------------------------
# pylint: disable=line-too-long, broad-except, logging-format-interpolation


from knack.log import get_logger
from typing import Any, Dict

from azure.cli.core.azclierror import ValidationError
from azure.cli.core.commands import AzCliCommand
from azure.cli.command_modules.containerapp.base_resource import BaseResource
from azure.cli.command_modules.containerapp._utils import safe_get
from ._clients import SessionPoolPreviewClient

from ._models import SessionCodeInterpreterExecution as SessionCodeInterpreterExecutionPreviewModel
from ._client_factory import handle_raw_exception
from .containerapp_sessionpool_decorator import ContainerType

logger = get_logger(__name__)


class SessionCustomContainerPreviewDecorator(BaseResource):
def __init__(self, cmd: AzCliCommand, client: Any, raw_parameters: Dict, models: str):
super().__init__(cmd, client, raw_parameters, models)
self.session_code_interpreter_def = SessionCodeInterpreterExecutionPreviewModel
self.session_pool_client = SessionPoolPreviewClient

def get_argument_name(self):
return self.get_param('name')

def get_argument_resource_group_name(self):
return self.get_param('resource_group_name')

def get_argument_identifier(self):
return self.get_param('identifier')

def get_sessionpool(self):
return self.session_pool_client.show(cmd=self.cmd,
resource_group_name=self.get_argument_resource_group_name(),
name=self.get_argument_name())


class SessionCustomContainerCommandsPreviewDecorator(SessionCustomContainerPreviewDecorator):
def stop_session(self):
try:
existing_pool_def = self.get_sessionpool()
if safe_get(existing_pool_def, "properties", "containerType").lower() != ContainerType.CustomContainer.name.lower():
raise ValidationError("Stop session operation is only supported for session pools with type 'CustomContainer'.")

return self.client.stop_session(
cmd=self.cmd,
identifier=self.get_argument_identifier(),
session_pool_endpoint=existing_pool_def["properties"]["poolManagementEndpoint"])
except Exception as e:
handle_raw_exception(e)
21 changes: 21 additions & 0 deletions src/containerapp/azext_containerapp/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
)
from .containerapp_sessionpool_decorator import SessionPoolPreviewDecorator, SessionPoolCreateDecorator, SessionPoolUpdateDecorator
from .containerapp_session_code_interpreter_decorator import SessionCodeInterpreterCommandsPreviewDecorator
from .containerapp_session_custom_container_decorator import SessionCustomContainerCommandsPreviewDecorator
from .containerapp_job_registry_decorator import ContainerAppJobRegistryPreviewSetDecorator
from .containerapp_env_maintenance_config_decorator import ContainerAppEnvMaintenanceConfigPreviewDecorator
from .dotnet_component_decorator import DotNetComponentDecorator
Expand All @@ -111,6 +112,7 @@
JavaComponentPreviewClient,
SessionPoolPreviewClient,
SessionCodeInterpreterPreviewClient,
SessionCustomContainerPreviewClient,
DotNetComponentPreviewClient,
MaintenanceConfigPreviewClient,
HttpRouteConfigPreviewClient,
Expand Down Expand Up @@ -3349,6 +3351,25 @@ def delete_file_session_code_interpreter(cmd,
return r


# session custom container commands
def stop_session_custom_container(cmd,
name,
resource_group_name,
identifier):
raw_parameters = locals()
session_custom_container_decorator = SessionCustomContainerCommandsPreviewDecorator(
cmd=cmd,
client=SessionCustomContainerPreviewClient,
raw_parameters=raw_parameters,
models=CONTAINER_APPS_SDK_MODELS
)
session_custom_container_decorator.register_provider(CONTAINER_APPS_RP)

r = session_custom_container_decorator.stop_session()

return r


def list_dotnet_components(cmd, environment_name, resource_group_name):
raw_parameters = locals()
dotnet_component_decorator = DotNetComponentDecorator(
Expand Down
Loading
Loading