Skip to content

Commit 88ab1f6

Browse files
committed
adding az containerapp function keys commands
1 parent cd79464 commit 88ab1f6

File tree

7 files changed

+395
-2
lines changed

7 files changed

+395
-2
lines changed

src/containerapp/HISTORY.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ Release History
44
===============
55
upcoming
66
++++++
7+
* 'az containerapp function list-keys': List function keys for a specific function in a container app
8+
* 'az containerapp function update-keys': Update specific function key for a specific function in a container app
9+
* 'az containerapp function list-hostkeys': List host keys for a container app
10+
* 'az containerapp function update-hostkeys': Update specific host key for a container app
711
* 'az containerapp update/up': Disallow changing `--revisions-mode` to Labels.
812
* 'az containerapp session code-interpreter': Fix `--path` in examples
913
* 'az containerapp sessionpool create/update': Support `--lifecycle-type` and `--max-alive-period`

src/containerapp/azext_containerapp/_clients.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,3 +1698,79 @@ def remove(cls, cmd, resource_group_name, environment_name):
16981698
if r.status_code == 202:
16991699
operation_url = r.headers.get(HEADER_LOCATION)
17001700
poll_results(cmd, operation_url)
1701+
1702+
class ContainerAppFunctionsPreviewClient:
1703+
api_version = PREVIEW_API_VERSION
1704+
1705+
@classmethod
1706+
def list_function_keys(cls, cmd, resource_group_name, name, function_name):
1707+
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
1708+
sub_id = get_subscription_id(cmd.cli_ctx)
1709+
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerapps/{}/functions/{}/listkeys?api-version={}"
1710+
request_url = url_fmt.format(
1711+
management_hostname.strip('/'),
1712+
sub_id,
1713+
resource_group_name,
1714+
name,
1715+
function_name,
1716+
cls.api_version)
1717+
1718+
r = send_raw_request(cmd.cli_ctx, "POST", request_url)
1719+
return r.json()
1720+
1721+
@classmethod
1722+
def update_function_keys(cls, cmd, resource_group_name, name, function_name, key_name, key_value=None):
1723+
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
1724+
sub_id = get_subscription_id(cmd.cli_ctx)
1725+
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerapps/{}/functions/{}/keys/{}?api-version={}"
1726+
request_url = url_fmt.format(
1727+
management_hostname.strip('/'),
1728+
sub_id,
1729+
resource_group_name,
1730+
name,
1731+
function_name,
1732+
key_name,
1733+
cls.api_version)
1734+
1735+
body = {}
1736+
if key_value:
1737+
body["value"] = key_value
1738+
1739+
r = send_raw_request(cmd.cli_ctx, "PUT", request_url, body=json.dumps(body))
1740+
return r.json()
1741+
1742+
@classmethod
1743+
def list_host_keys(cls, cmd, resource_group_name, name):
1744+
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
1745+
sub_id = get_subscription_id(cmd.cli_ctx)
1746+
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerapps/{}/host/default/listkeys?api-version={}"
1747+
request_url = url_fmt.format(
1748+
management_hostname.strip('/'),
1749+
sub_id,
1750+
resource_group_name,
1751+
name,
1752+
cls.api_version)
1753+
1754+
r = send_raw_request(cmd.cli_ctx, "POST", request_url)
1755+
return r.json()
1756+
1757+
@classmethod
1758+
def update_host_keys(cls, cmd, resource_group_name, name, key_type, key_name, key_value=None):
1759+
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
1760+
sub_id = get_subscription_id(cmd.cli_ctx)
1761+
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerapps/{}/host/default/{}/{}?api-version={}"
1762+
request_url = url_fmt.format(
1763+
management_hostname.strip('/'),
1764+
sub_id,
1765+
resource_group_name,
1766+
name,
1767+
key_type,
1768+
key_name,
1769+
cls.api_version)
1770+
1771+
body = {}
1772+
if key_value:
1773+
body["value"] = key_value
1774+
1775+
r = send_raw_request(cmd.cli_ctx, "PUT", request_url, body=json.dumps(body))
1776+
return r.json()

src/containerapp/azext_containerapp/_help.py

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@
166166
az containerapp up -n my-containerapp --image my-app:v1.0 --kind functionapp
167167
"""
168168

169-
170169
helps['containerapp replica count'] = """
171170
type: command
172171
short-summary: Count of a container app's replica(s)
@@ -179,6 +178,53 @@
179178
az containerapp replica count -n my-containerapp -g MyResourceGroup
180179
"""
181180

181+
helps['containerapp function'] = """
182+
type: group
183+
short-summary: Commands to manage function keys in a container app.
184+
"""
185+
186+
helps['containerapp function list-keys'] = """
187+
type: command
188+
short-summary: List function keys for a specific function in a container app.
189+
examples:
190+
- name: List function keys for a specific function
191+
text: |
192+
az containerapp function list-keys -n my-containerapp -g MyResourceGroup --revision MyContainerappRevision --function-name MyFunctionName
193+
"""
194+
195+
helps['containerapp function update-keys'] = """
196+
type: command
197+
short-summary: Update function keys for a specific function in a container app.
198+
examples:
199+
- name: Update a function key for a specific function
200+
text: |
201+
az containerapp function update-keys -n my-containerapp -g MyResourceGroup --revision MyContainerappRevision --function-name MyFunctionName --key-name MyKeyName --key-value MyKeyValue
202+
"""
203+
204+
helps['containerapp function list-hostkeys'] = """
205+
type: command
206+
short-summary: List host keys for a container app.
207+
examples:
208+
- name: List host keys for a container app
209+
text: |
210+
az containerapp function list-hostkeys -n my-containerapp -g MyResourceGroup --revision MyContainerappRevision
211+
"""
212+
213+
helps['containerapp function update-hostkeys'] = """
214+
type: command
215+
short-summary: Update host keys for a container app.
216+
examples:
217+
- name: Update a host key for a container app with function key type
218+
text: |
219+
az containerapp function update-hostkeys -n my-containerapp -g MyResourceGroup --revision MyContainerappRevision --key-name MyKeyName --key-value MyKeyValue --key-type functionKeys
220+
- name: Update a host key for a container app with master key type
221+
text: |
222+
az containerapp function update-hostkeys -n my-containerapp -g MyResourceGroup --revision MyContainerappRevision --key-name MyKeyName --key-value MyKeyValue --key-type masterKey
223+
- name: Update a host key for a container app with system key type
224+
text: |
225+
az containerapp function update-hostkeys -n my-containerapp -g MyResourceGroup --revision MyContainerappRevision --key-name MyKeyName --key-value MyKeyValue --key-type systemKeys
226+
"""
227+
182228
# Environment Commands
183229
helps['containerapp env'] = """
184230
type: group

src/containerapp/azext_containerapp/_params.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,3 +529,30 @@ 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 function list-keys') 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', options_list=['--revision'], help="The name of the container app revision.")
537+
c.argument('function_name', options_list=['--function-name'], help="The name of the function.")
538+
539+
with self.argument_context('containerapp function update-keys') as c:
540+
c.argument('resource_group_name', arg_type=resource_group_name_type, id_part=None)
541+
c.argument('name', options_list=['--name', '-n'], help="The name of the container app.")
542+
c.argument('revision', options_list=['--revision'], help="The name of the container app revision.")
543+
c.argument('function_name', options_list=['--function-name'], help="The name of the function.")
544+
c.argument('key_name', options_list=['--key-name'], help="The name of the key to update.")
545+
c.argument('key_value', options_list=['--key-value'], help="The value of the key to update.")
546+
547+
with self.argument_context('containerapp function list-hostkeys') as c:
548+
c.argument('resource_group_name', arg_type=resource_group_name_type, id_part=None)
549+
c.argument('name', options_list=['--name', '-n'], help="The name of the container app.")
550+
c.argument('revision', options_list=['--revision'], help="The name of the container app revision.")
551+
552+
with self.argument_context('containerapp function update-hostkeys') as c:
553+
c.argument('resource_group_name', arg_type=resource_group_name_type, id_part=None)
554+
c.argument('name', options_list=['--name', '-n'], help="The name of the container app.")
555+
c.argument('revision', options_list=['--revision'], help="The name of the container app revision.")
556+
c.argument('key_name', options_list=['--key-name'], help="The name of the host key to update.")
557+
c.argument('key_value', options_list=['--key-value'], help="The value of the host key to update.")
558+
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: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,3 +297,9 @@ def load_command_table(self, args):
297297
g.custom_command('add', 'add_environment_premium_ingress')
298298
g.custom_command('update', 'update_environment_premium_ingress')
299299
g.custom_command('remove', 'remove_environment_premium_ingress', confirmation=True)
300+
301+
with self.command_group('containerapp function') as g:
302+
g.custom_command('list-keys', 'list_containerapp_function_keys')
303+
g.custom_command('update-keys', 'update_containerapp_function_keys')
304+
g.custom_command('list-hostkeys', 'list_containerapp_function_hostkeys')
305+
g.custom_command('update-hostkeys', 'update_containerapp_function_hostkeys')
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
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
7+
from knack.log import get_logger
8+
from typing import Any, Dict
9+
10+
from azure.cli.core.commands import AzCliCommand
11+
from azure.cli.core.azclierror import ValidationError
12+
from azure.cli.command_modules.containerapp.base_resource import BaseResource
13+
14+
from ._clients import ContainerAppFunctionsPreviewClient
15+
from ._client_factory import handle_raw_exception
16+
17+
logger = get_logger(__name__)
18+
19+
20+
class ContainerAppFunctionsDecorator(BaseResource):
21+
"""Base decorator for Container App Functions operations"""
22+
23+
def __init__(self, cmd: AzCliCommand, client: Any, raw_parameters: Dict, models: str):
24+
super().__init__(cmd, client, raw_parameters, models)
25+
26+
def get_argument_function_name(self):
27+
return self.get_param("function_name")
28+
29+
30+
class ContainerAppFunctionKeysListDecorator(ContainerAppFunctionsDecorator):
31+
"""Decorator for listing function keys"""
32+
33+
def __init__(self, cmd: AzCliCommand, client: Any, raw_parameters: Dict, models: str):
34+
super().__init__(cmd, client, raw_parameters, models)
35+
36+
def list_keys(self):
37+
"""List keys for a specific function"""
38+
try:
39+
function_name = self.get_argument_function_name()
40+
resource_group_name = self.get_argument_resource_group_name()
41+
name = self.get_argument_name()
42+
43+
if not resource_group_name:
44+
raise ValidationError("Resource group name is required.")
45+
46+
if not name:
47+
raise ValidationError("Container app name is required.")
48+
49+
if not function_name:
50+
raise ValidationError("Function name is required.")
51+
52+
return self.client.list_function_keys(
53+
cmd=self.cmd,
54+
resource_group_name=resource_group_name,
55+
name=name,
56+
function_name=function_name
57+
)
58+
except Exception as e:
59+
handle_raw_exception(e)
60+
61+
62+
class ContainerAppFunctionKeysUpdateDecorator(ContainerAppFunctionsDecorator):
63+
"""Decorator for updating function keys"""
64+
65+
def __init__(self, cmd: AzCliCommand, client: Any, raw_parameters: Dict, models: str):
66+
super().__init__(cmd, client, raw_parameters, models)
67+
68+
def get_argument_key_name(self):
69+
return self.get_param("key_name")
70+
71+
def get_argument_key_value(self):
72+
return self.get_param("key_value")
73+
74+
def update_keys(self):
75+
"""Update keys for a specific function"""
76+
try:
77+
function_name = self.get_argument_function_name()
78+
key_name = self.get_argument_key_name()
79+
key_value = self.get_argument_key_value()
80+
resource_group_name = self.get_argument_resource_group_name()
81+
name = self.get_argument_name()
82+
83+
if not resource_group_name:
84+
raise ValidationError("Resource group name is required.")
85+
86+
if not name:
87+
raise ValidationError("Container app name is required.")
88+
89+
if not function_name:
90+
raise ValidationError("Function name is required.")
91+
92+
if not key_name:
93+
raise ValidationError("Key name is required.")
94+
95+
return self.client.update_function_keys(
96+
cmd=self.cmd,
97+
resource_group_name=resource_group_name,
98+
name=name,
99+
function_name=function_name,
100+
key_name=key_name,
101+
key_value=key_value
102+
)
103+
except Exception as e:
104+
handle_raw_exception(e)
105+
106+
107+
class ContainerAppFunctionHostKeysListDecorator(ContainerAppFunctionsDecorator):
108+
"""Decorator for listing host keys"""
109+
110+
def __init__(self, cmd: AzCliCommand, client: Any, raw_parameters: Dict, models: str):
111+
super().__init__(cmd, client, raw_parameters, models)
112+
113+
def list_host_keys(self):
114+
"""List host keys for the container app function host"""
115+
try:
116+
resource_group_name = self.get_argument_resource_group_name()
117+
name = self.get_argument_name()
118+
119+
if not resource_group_name:
120+
raise ValidationError("Resource group name is required.")
121+
122+
if not name:
123+
raise ValidationError("Container app name is required.")
124+
125+
return self.client.list_host_keys(
126+
cmd=self.cmd,
127+
resource_group_name=resource_group_name,
128+
name=name
129+
)
130+
except Exception as e:
131+
handle_raw_exception(e)
132+
133+
134+
class ContainerAppFunctionHostKeysUpdateDecorator(ContainerAppFunctionsDecorator):
135+
"""Decorator for updating host keys"""
136+
137+
def __init__(self, cmd: AzCliCommand, client: Any, raw_parameters: Dict, models: str):
138+
super().__init__(cmd, client, raw_parameters, models)
139+
140+
def get_argument_key_type(self):
141+
return self.get_param("key_type")
142+
143+
def get_argument_key_name(self):
144+
return self.get_param("key_name")
145+
146+
def get_argument_key_value(self):
147+
return self.get_param("key_value")
148+
149+
def update_host_keys(self):
150+
"""Update host keys for the container app function host"""
151+
try:
152+
key_type = self.get_argument_key_type()
153+
key_name = self.get_argument_key_name()
154+
key_value = self.get_argument_key_value()
155+
resource_group_name = self.get_argument_resource_group_name()
156+
name = self.get_argument_name()
157+
158+
if not resource_group_name:
159+
raise ValidationError("Resource group name is required.")
160+
161+
if not name:
162+
raise ValidationError("Container app name is required.")
163+
164+
if not key_type:
165+
raise ValidationError("Key type is required.")
166+
167+
if not key_name:
168+
raise ValidationError("Key name is required.")
169+
170+
return self.client.update_host_keys(
171+
cmd=self.cmd,
172+
resource_group_name=resource_group_name,
173+
name=name,
174+
key_type=key_type,
175+
key_name=key_name,
176+
key_value=key_value
177+
)
178+
except Exception as e:
179+
handle_raw_exception(e)

0 commit comments

Comments
 (0)