Skip to content

Commit a34da44

Browse files
Merge pull request #2 from khushishah513/functionaca-getlist
[Container App] az containerapp function: Add list and show commands for container app functions
2 parents 0cf0be6 + 771087c commit a34da44

File tree

7 files changed

+285
-11
lines changed

7 files changed

+285
-11
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 function show/list': New command group to list and show functions in container apps.
78
* 'az containerapp function list-keys': List function keys for a specific function in a container app
89
* 'az containerapp function update-keys': Update specific function key for a specific function in a container app
910
* 'az containerapp function list-hostkeys': List host keys for a container app

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 in single revision mode"""
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 in single revision mode"""
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: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,37 @@
180180

181181
helps['containerapp function'] = """
182182
type: group
183-
short-summary: Commands to manage function keys in a container app.
183+
short-summary: Commands related to Azure Function on Azure Container Apps.
184+
"""
185+
186+
helps['containerapp function list'] = """
187+
type: command
188+
short-summary: List all functions in a container app or a specific revision. (pass --revisionName parameter)
189+
long-summary: |
190+
revisionName is required only if Container App active Revision Mode is setup in Multiple Revision Mode. (Default: Single Revision Mode)
191+
Run to check activerevisionmode: az containerapp show -n my-containerapp -g MyResourceGroup --query properties.configuration.activeRevisionsMode
192+
examples:
193+
- name: List all functions in a container app. (single active revision mode)
194+
text: |
195+
az containerapp function list -n my-containerapp -g MyResourceGroup
196+
- name: List all functions for a specific revision
197+
text: |
198+
az containerapp function list -n my-containerapp -g MyResourceGroup --revision-name MyRevision
199+
"""
200+
201+
helps['containerapp function show'] = """
202+
type: command
203+
short-summary: Show details of a specific function in a container app or a specific revision within app. (pass --revisionName parameter)
204+
long-summary: |
205+
revisionName is required only if Container App active Revision Mode is setup in Multiple Revision Mode. (Default: Single Revision Mode)
206+
Run to check activerevisionmode: az containerapp show -n my-containerapp -g MyResourceGroup --query properties.configuration.activeRevisionsMode
207+
examples:
208+
- name: Show details of a function in a container app. (single active revision mode)
209+
text: |
210+
az containerapp function show -n my-containerapp -g MyResourceGroup --function-name MyFunction
211+
- name: Show details of a function for a specific revision
212+
text: |
213+
az containerapp function show -n my-containerapp -g MyResourceGroup --function-name MyFunction --revision-name MyRevision
184214
"""
185215

186216
helps['containerapp function list-keys'] = """

src/containerapp/azext_containerapp/_params.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -530,30 +530,33 @@ def load_arguments(self, _):
530530
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.")
531531
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.")
532532
c.argument('header_count_limit', options_list=['--header-count-limit'], type=int, help="Limit of http headers per request. Default 100, minimum 1.")
533+
534+
with self.argument_context('containerapp function') as c:
535+
c.argument('resource_group_name', arg_type=resource_group_name_type, id_part=None)
536+
c.argument('name', options_list=['--name', '-n'], help="The name of the Container App.")
537+
538+
with self.argument_context('containerapp function list') as c:
539+
c.argument('revision_name', options_list=['--revision-name', '-r'], help="The name of the revision to list functions from. It is required if container app is running in multiple active revision mode.")
540+
541+
with self.argument_context('containerapp function show') as c:
542+
c.argument('function_name', options_list=['--function-name', '-f'], help="The name of the function to show details for.")
543+
c.argument('revision_name', options_list=['--revision-name', '-r'], help="The name of the revision to get the function from. It is required if container app is running in multiple active revision mode.")
533544

534545
with self.argument_context('containerapp function list-keys') as c:
535-
c.argument('resource_group_name', arg_type=resource_group_name_type, id_part=None)
536-
c.argument('name', options_list=['--name', '-n'], help="The name of the container app.")
537546
c.argument('revision', options_list=['--revision'], help="The name of the container app revision.")
538547
c.argument('function_name', options_list=['--function-name'], help="The name of the function.")
539548

540549
with self.argument_context('containerapp function update-keys') as c:
541-
c.argument('resource_group_name', arg_type=resource_group_name_type, id_part=None)
542-
c.argument('name', options_list=['--name', '-n'], help="The name of the container app.")
543550
c.argument('revision', options_list=['--revision'], help="The name of the container app revision.")
544551
c.argument('function_name', options_list=['--function-name'], help="The name of the function.")
545552
c.argument('key_name', options_list=['--key-name'], help="The name of the key to update.")
546553
c.argument('key_value', options_list=['--key-value'], help="The value of the key to update.")
547554

548555
with self.argument_context('containerapp function list-hostkeys') as c:
549-
c.argument('resource_group_name', arg_type=resource_group_name_type, id_part=None)
550-
c.argument('name', options_list=['--name', '-n'], help="The name of the container app.")
551556
c.argument('revision', options_list=['--revision'], help="The name of the container app revision.")
552557

553558
with self.argument_context('containerapp function update-hostkeys') as c:
554-
c.argument('resource_group_name', arg_type=resource_group_name_type, id_part=None)
555-
c.argument('name', options_list=['--name', '-n'], help="The name of the container app.")
556559
c.argument('revision', options_list=['--revision'], help="The name of the container app revision.")
557560
c.argument('key_name', options_list=['--key-name'], help="The name of the host key to update.")
558561
c.argument('key_value', options_list=['--key-value'], help="The value of the host key to update.")
559-
c.argument('key_type', options_list=['--key-type'], arg_type=get_enum_type(['functionKeys', 'masterKey', 'systemKeys']), help="The type of the host key.")
562+
c.argument('key_type', options_list=['--key-type'], arg_type=get_enum_type(['functionKeys', 'masterKey', 'systemKeys']), help="The type of the host key.")

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 function', 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: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
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 not resource_group_name:
60+
raise ValidationError("Resource group name is required.")
61+
62+
if not container_app_name:
63+
raise ValidationError("Container app name is required.")
64+
65+
if revision_name:
66+
# List functions for a specific revision
67+
return self.client.list_functions_by_revision(
68+
cmd=self.cmd,
69+
resource_group_name=resource_group_name,
70+
container_app_name=container_app_name,
71+
revision_name=revision_name
72+
)
73+
else:
74+
# List functions for the entire container app
75+
return self.client.list_functions(
76+
cmd=self.cmd,
77+
resource_group_name=resource_group_name,
78+
container_app_name=container_app_name
79+
)
80+
except Exception as e:
81+
handle_raw_exception(e)
82+
83+
84+
class ContainerAppFunctionsShowDecorator(ContainerAppFunctionsDecorator):
85+
"""Decorator for showing a specific function"""
86+
87+
def __init__(self, cmd: AzCliCommand, client: Any, raw_parameters: Dict, models: str):
88+
super().__init__(cmd, client, raw_parameters, models)
89+
90+
def show(self):
91+
"""Show details of a specific function"""
92+
try:
93+
revision_name = self.get_argument_revision_name()
94+
container_app_name = self.get_argument_container_app_name()
95+
function_name = self.get_argument_function_name()
96+
resource_group_name = self.get_argument_resource_group_name()
97+
98+
if not resource_group_name:
99+
raise ValidationError("Resource group name is required.")
100+
101+
if not container_app_name:
102+
raise ValidationError("Container app name is required.")
103+
104+
if not function_name:
105+
raise ValidationError("Function name is required.")
106+
107+
if revision_name:
108+
# Get function for a specific revision
109+
return self.client.get_function_by_revision(
110+
cmd=self.cmd,
111+
resource_group_name=resource_group_name,
112+
container_app_name=container_app_name,
113+
revision_name=revision_name,
114+
function_name=function_name
115+
)
116+
else:
117+
# Get function for the entire container app
118+
return self.client.get_function(
119+
cmd=self.cmd,
120+
resource_group_name=resource_group_name,
121+
container_app_name=container_app_name,
122+
function_name=function_name
123+
)
124+
except Exception as e:
125+
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 .containerapp_function_keys_decorator import (
97101
ContainerAppFunctionKeysListDecorator,
98102
ContainerAppFunctionKeysUpdateDecorator,
@@ -3947,6 +3951,40 @@ def remove_environment_premium_ingress(cmd, name, resource_group_name, no_wait=F
39473951
except Exception as e:
39483952
handle_raw_exception(e)
39493953

3954+
3955+
# Container App Functions commands
3956+
def list_containerapp_functions(cmd, resource_group_name, name, revision_name=None):
3957+
"""List functions for a container app or specific revision"""
3958+
containerapp_functions_list_decorator = ContainerAppFunctionsListDecorator(
3959+
cmd=cmd,
3960+
client=ContainerAppFunctionsPreviewClient,
3961+
raw_parameters={
3962+
'resource_group_name': resource_group_name,
3963+
'container_app_name': name,
3964+
'revision_name': revision_name
3965+
},
3966+
models=CONTAINER_APPS_SDK_MODELS
3967+
)
3968+
3969+
return containerapp_functions_list_decorator.list()
3970+
3971+
3972+
def show_containerapp_function(cmd, resource_group_name, name, function_name, revision_name=None):
3973+
"""Show details of a specific function for a container app or revision"""
3974+
containerapp_functions_show_decorator = ContainerAppFunctionsShowDecorator(
3975+
cmd=cmd,
3976+
client=ContainerAppFunctionsPreviewClient,
3977+
raw_parameters={
3978+
'resource_group_name': resource_group_name,
3979+
'container_app_name': name,
3980+
'function_name': function_name,
3981+
'revision_name': revision_name
3982+
},
3983+
models=CONTAINER_APPS_SDK_MODELS
3984+
)
3985+
3986+
return containerapp_functions_show_decorator.show()
3987+
39503988
# Container App Function Key Commands
39513989
def list_containerapp_function_keys(cmd, name, resource_group_name, function_name, revision=None):
39523990
"""List function keys for a specific function"""
@@ -3993,4 +4031,5 @@ def update_containerapp_function_hostkeys(cmd, name, resource_group_name, key_ty
39934031
raw_parameters=raw_parameters,
39944032
models=CONTAINER_APPS_SDK_MODELS
39954033
)
3996-
return containerapp_function_decorator.update_host_keys()
4034+
return containerapp_function_decorator.update_host_keys()
4035+

0 commit comments

Comments
 (0)