Skip to content

Commit 4dc363f

Browse files
committed
adding az containerapp functions commands
1 parent cd79464 commit 4dc363f

File tree

7 files changed

+272
-1
lines changed

7 files changed

+272
-1
lines changed

src/containerapp/HISTORY.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Release History
44
===============
55
upcoming
66
++++++
7+
* 'az containerapp functions get/list': New command group to list and show functions in container apps.
78
* 'az containerapp update/up': Disallow changing `--revisions-mode` to Labels.
89
* 'az containerapp session code-interpreter': Fix `--path` in examples
910
* 'az containerapp sessionpool create/update': Support `--lifecycle-type` and `--max-alive-period`

src/containerapp/azext_containerapp/_clients.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,78 @@ def list(cls, cmd, resource_group_name, container_app_name):
303303
return policy_list
304304

305305

306+
class ContainerAppFunctionsPreviewClient():
307+
api_version = PREVIEW_API_VERSION
308+
309+
@classmethod
310+
def list_functions_by_revision(cls, cmd, resource_group_name, container_app_name, revision_name):
311+
"""List all functions for a specific revision"""
312+
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
313+
sub_id = get_subscription_id(cmd.cli_ctx)
314+
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/revisions/{}/functions?api-version={}"
315+
request_url = url_fmt.format(
316+
management_hostname.strip('/'),
317+
sub_id,
318+
resource_group_name,
319+
container_app_name,
320+
revision_name,
321+
cls.api_version)
322+
323+
r = send_raw_request(cmd.cli_ctx, "GET", request_url)
324+
return r.json()
325+
326+
@classmethod
327+
def get_function_by_revision(cls, cmd, resource_group_name, container_app_name, revision_name, function_name):
328+
"""Get a specific function for a specific revision"""
329+
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
330+
sub_id = get_subscription_id(cmd.cli_ctx)
331+
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/revisions/{}/functions/{}?api-version={}"
332+
request_url = url_fmt.format(
333+
management_hostname.strip('/'),
334+
sub_id,
335+
resource_group_name,
336+
container_app_name,
337+
revision_name,
338+
function_name,
339+
cls.api_version)
340+
341+
r = send_raw_request(cmd.cli_ctx, "GET", request_url)
342+
return r.json()
343+
344+
@classmethod
345+
def list_functions(cls, cmd, resource_group_name, container_app_name):
346+
"""List all functions for a container app (across all revisions)"""
347+
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
348+
sub_id = get_subscription_id(cmd.cli_ctx)
349+
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/functions?api-version={}"
350+
request_url = url_fmt.format(
351+
management_hostname.strip('/'),
352+
sub_id,
353+
resource_group_name,
354+
container_app_name,
355+
cls.api_version)
356+
357+
r = send_raw_request(cmd.cli_ctx, "GET", request_url)
358+
return r.json()
359+
360+
@classmethod
361+
def get_function(cls, cmd, resource_group_name, container_app_name, function_name):
362+
"""Get a specific function for a container app"""
363+
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
364+
sub_id = get_subscription_id(cmd.cli_ctx)
365+
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/functions/{}?api-version={}"
366+
request_url = url_fmt.format(
367+
management_hostname.strip('/'),
368+
sub_id,
369+
resource_group_name,
370+
container_app_name,
371+
function_name,
372+
cls.api_version)
373+
374+
r = send_raw_request(cmd.cli_ctx, "GET", request_url)
375+
return r.json()
376+
377+
306378
class DaprComponentResiliencyPreviewClient():
307379
api_version = PREVIEW_API_VERSION
308380

src/containerapp/azext_containerapp/_help.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,39 @@
179179
az containerapp replica count -n my-containerapp -g MyResourceGroup
180180
"""
181181

182+
helps['containerapp functions'] = """
183+
type: group
184+
short-summary: Commands to view functions in a container app.
185+
"""
186+
187+
helps['containerapp functions list'] = """
188+
type: command
189+
short-summary: List all functions in a container app or a specific revision.
190+
long-summary: |
191+
When revision name is not provided, lists functions from the active revision. If there are multiple active revisions, the API will return an error requiring you to specify which revision.
192+
examples:
193+
- name: List all functions in a container app (single active revision mode)
194+
text: |
195+
az containerapp functions list -n my-containerapp -g MyResourceGroup
196+
- name: List all functions for a specific revision
197+
text: |
198+
az containerapp functions list -n my-containerapp -g MyResourceGroup --revision-name MyRevision
199+
"""
200+
201+
helps['containerapp functions show'] = """
202+
type: command
203+
short-summary: Show details of a specific function in a container app.
204+
long-summary: |
205+
When revision name is not provided, shows function from the active revision. If there are multiple active revisions, the API will return an error requiring you to specify which revision.
206+
examples:
207+
- name: Show details of a function in a container app (single active revision mode)
208+
text: |
209+
az containerapp functions show -n my-containerapp -g MyResourceGroup --function-name MyFunction
210+
- name: Show details of a function for a specific revision
211+
text: |
212+
az containerapp functions show -n my-containerapp -g MyResourceGroup --function-name MyFunction --revision-name MyRevision
213+
"""
214+
182215
# Environment Commands
183216
helps['containerapp env'] = """
184217
type: group

src/containerapp/azext_containerapp/_params.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,3 +529,12 @@ def load_arguments(self, _):
529529
c.argument('termination_grace_period', options_list=['--termination-grace-period', '-t'], type=int, help="Time in seconds to drain requests during ingress shutdown. Default 500, minimum 0, maximum 3600.")
530530
c.argument('request_idle_timeout', options_list=['--request-idle-timeout'], type=int, help="Timeout in minutes for idle requests. Default 4, minimum 4, maximum 30.")
531531
c.argument('header_count_limit', options_list=['--header-count-limit'], type=int, help="Limit of http headers per request. Default 100, minimum 1.")
532+
533+
with self.argument_context('containerapp functions list') as c:
534+
c.argument('resource_group_name', arg_type=resource_group_name_type, id_part=None)
535+
c.argument('name', options_list=['--name', '-n'], help="The name of the Container App.")
536+
c.argument('revision_name', options_list=['--revision-name', '-r'], help="The name of the revision to list functions from. If not provided, lists functions from the active revision (only works if there's a single active revision).")
537+
538+
with self.argument_context('containerapp functions show') as c:
539+
c.argument('function_name', options_list=['--function-name', '-f'], help="The name of the function to show details for.")
540+
c.argument('revision_name', options_list=['--revision-name', '-r'], help="The name of the revision to get the function from. If not provided, gets function from the active revision (only works if there's a single active revision).")

src/containerapp/azext_containerapp/commands.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ def load_command_table(self, args):
3232
g.custom_command('list', 'list_replicas')
3333
g.custom_command('count', 'count_replicas', is_preview=True)
3434

35+
with self.command_group('containerapp functions', is_preview=True) as g:
36+
g.custom_command('list', 'list_containerapp_functions')
37+
g.custom_show_command('show', 'show_containerapp_function')
38+
3539
with self.command_group('containerapp env') as g:
3640
g.custom_show_command('show', 'show_managed_environment')
3741
g.custom_command('list', 'list_managed_environments')
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# coding=utf-8
2+
# --------------------------------------------------------------------------------------------
3+
# Copyright (c) Microsoft Corporation. All rights reserved.
4+
# Licensed under the MIT License. See License.txt in the project root for license information.
5+
# --------------------------------------------------------------------------------------------
6+
# pylint: disable=line-too-long, broad-except, logging-format-interpolation, too-many-public-methods, too-many-boolean-expressions, logging-fstring-interpolation
7+
8+
from knack.log import get_logger
9+
from typing import Any, Dict
10+
11+
from azure.cli.core.commands import AzCliCommand
12+
from azure.cli.core.azclierror import (ValidationError, ResourceNotFoundError)
13+
from azure.cli.command_modules.containerapp.base_resource import BaseResource
14+
15+
from ._clients import ContainerAppFunctionsPreviewClient
16+
from ._client_factory import handle_raw_exception
17+
18+
logger = get_logger(__name__)
19+
20+
21+
class ContainerAppFunctionsDecorator(BaseResource):
22+
"""Base decorator for Container App Functions operations"""
23+
24+
def __init__(self, cmd: AzCliCommand, client: Any, raw_parameters: Dict, models: str):
25+
super().__init__(cmd, client, raw_parameters, models)
26+
27+
def get_argument_container_app_name(self):
28+
return self.get_param("container_app_name")
29+
30+
def get_argument_revision_name(self):
31+
return self.get_param("revision_name")
32+
33+
def get_argument_function_name(self):
34+
return self.get_param("function_name")
35+
36+
def set_argument_container_app_name(self, container_app_name):
37+
self.set_param("container_app_name", container_app_name)
38+
39+
def set_argument_revision_name(self, revision_name):
40+
self.set_param("revision_name", revision_name)
41+
42+
def set_argument_function_name(self, function_name):
43+
self.set_param("function_name", function_name)
44+
45+
46+
class ContainerAppFunctionsListDecorator(ContainerAppFunctionsDecorator):
47+
"""Decorator for listing functions"""
48+
49+
def __init__(self, cmd: AzCliCommand, client: Any, raw_parameters: Dict, models: str):
50+
super().__init__(cmd, client, raw_parameters, models)
51+
52+
def list(self):
53+
"""List functions for a container app or revision"""
54+
try:
55+
revision_name = self.get_argument_revision_name()
56+
container_app_name = self.get_argument_container_app_name()
57+
resource_group_name = self.get_argument_resource_group_name()
58+
59+
if revision_name:
60+
# List functions for a specific revision
61+
return self.client.list_functions_by_revision(
62+
cmd=self.cmd,
63+
resource_group_name=resource_group_name,
64+
container_app_name=container_app_name,
65+
revision_name=revision_name
66+
)
67+
else:
68+
# List functions for the entire container app
69+
return self.client.list_functions(
70+
cmd=self.cmd,
71+
resource_group_name=resource_group_name,
72+
container_app_name=container_app_name
73+
)
74+
except Exception as e:
75+
handle_raw_exception(e)
76+
77+
78+
class ContainerAppFunctionsShowDecorator(ContainerAppFunctionsDecorator):
79+
"""Decorator for showing a specific function"""
80+
81+
def __init__(self, cmd: AzCliCommand, client: Any, raw_parameters: Dict, models: str):
82+
super().__init__(cmd, client, raw_parameters, models)
83+
84+
def show(self):
85+
"""Show details of a specific function"""
86+
try:
87+
revision_name = self.get_argument_revision_name()
88+
container_app_name = self.get_argument_container_app_name()
89+
function_name = self.get_argument_function_name()
90+
resource_group_name = self.get_argument_resource_group_name()
91+
92+
if not function_name:
93+
raise ValidationError("Function name is required.")
94+
95+
if revision_name:
96+
# Get function for a specific revision
97+
return self.client.get_function_by_revision(
98+
cmd=self.cmd,
99+
resource_group_name=resource_group_name,
100+
container_app_name=container_app_name,
101+
revision_name=revision_name,
102+
function_name=function_name
103+
)
104+
else:
105+
# Get function for the entire container app
106+
return self.client.get_function(
107+
cmd=self.cmd,
108+
resource_group_name=resource_group_name,
109+
container_app_name=container_app_name,
110+
function_name=function_name
111+
)
112+
except Exception as e:
113+
handle_raw_exception(e)

src/containerapp/azext_containerapp/custom.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@
9393
from .containerapp_session_code_interpreter_decorator import SessionCodeInterpreterCommandsPreviewDecorator
9494
from .containerapp_job_registry_decorator import ContainerAppJobRegistryPreviewSetDecorator
9595
from .containerapp_env_maintenance_config_decorator import ContainerAppEnvMaintenanceConfigPreviewDecorator
96+
from .containerapp_functions_decorator import (
97+
ContainerAppFunctionsListDecorator,
98+
ContainerAppFunctionsShowDecorator
99+
)
96100
from .dotnet_component_decorator import DotNetComponentDecorator
97101
from ._client_factory import handle_raw_exception, handle_non_404_status_code_exception
98102
from ._clients import (
@@ -114,7 +118,8 @@
114118
DotNetComponentPreviewClient,
115119
MaintenanceConfigPreviewClient,
116120
HttpRouteConfigPreviewClient,
117-
LabelHistoryPreviewClient
121+
LabelHistoryPreviewClient,
122+
ContainerAppFunctionsPreviewClient
118123
)
119124
from ._dev_service_utils import DevServiceUtils
120125
from ._models import (
@@ -3937,3 +3942,37 @@ def remove_environment_premium_ingress(cmd, name, resource_group_name, no_wait=F
39373942

39383943
except Exception as e:
39393944
handle_raw_exception(e)
3945+
3946+
3947+
# Container App Functions commands
3948+
def list_containerapp_functions(cmd, resource_group_name, name, revision_name=None):
3949+
"""List functions for a container app or specific revision"""
3950+
containerapp_functions_list_decorator = ContainerAppFunctionsListDecorator(
3951+
cmd=cmd,
3952+
client=ContainerAppFunctionsPreviewClient,
3953+
raw_parameters={
3954+
'resource_group_name': resource_group_name,
3955+
'container_app_name': name,
3956+
'revision_name': revision_name
3957+
},
3958+
models=CONTAINER_APPS_SDK_MODELS
3959+
)
3960+
3961+
return containerapp_functions_list_decorator.list()
3962+
3963+
3964+
def show_containerapp_function(cmd, resource_group_name, name, function_name, revision_name=None):
3965+
"""Show details of a specific function for a container app or revision"""
3966+
containerapp_functions_show_decorator = ContainerAppFunctionsShowDecorator(
3967+
cmd=cmd,
3968+
client=ContainerAppFunctionsPreviewClient,
3969+
raw_parameters={
3970+
'resource_group_name': resource_group_name,
3971+
'container_app_name': name,
3972+
'function_name': function_name,
3973+
'revision_name': revision_name
3974+
},
3975+
models=CONTAINER_APPS_SDK_MODELS
3976+
)
3977+
3978+
return containerapp_functions_show_decorator.show()

0 commit comments

Comments
 (0)