Skip to content
Closed
5 changes: 5 additions & 0 deletions src/containerapp/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ Release History
===============
upcoming
++++++
* 'az containerapp function show/list': New command group to list and show functions in container apps.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please review command from Nitesh/Deep

* 'az containerapp function list-keys': List function keys for a specific function in a container app
* 'az containerapp function update-keys': Update specific function key for a specific function in a container app
* 'az containerapp function list-hostkeys': List host keys for a container app
* 'az containerapp function update-hostkeys': Update specific host key for a container app
* 'az containerapp update/up': Disallow changing `--revisions-mode` to Labels.
* 'az containerapp session code-interpreter': Fix `--path` in examples
* 'az containerapp sessionpool create/update': Support `--lifecycle-type` and `--max-alive-period`
Expand Down
148 changes: 148 additions & 0 deletions src/containerapp/azext_containerapp/_clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,78 @@ def list(cls, cmd, resource_group_name, container_app_name):
return policy_list


class ContainerAppFunctionsPreviewClient():
api_version = PREVIEW_API_VERSION

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did we update PREVIEW_API_VERSION to the latest unreleased one? Add TODO for tracking, if not done.


@classmethod
def list_functions_by_revision(cls, cmd, resource_group_name, container_app_name, revision_name):
"""List all functions for a specific revision"""
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
sub_id = get_subscription_id(cmd.cli_ctx)
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/revisions/{}/functions?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
container_app_name,
revision_name,
cls.api_version)

r = send_raw_request(cmd.cli_ctx, "GET", request_url)
return r.json()

@classmethod
def get_function_by_revision(cls, cmd, resource_group_name, container_app_name, revision_name, function_name):
"""Get a specific function for a specific revision"""
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
sub_id = get_subscription_id(cmd.cli_ctx)
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/revisions/{}/functions/{}?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
container_app_name,
revision_name,
function_name,
cls.api_version)

r = send_raw_request(cmd.cli_ctx, "GET", request_url)
return r.json()

@classmethod
def list_functions(cls, cmd, resource_group_name, container_app_name):
"""List all functions for a container app in single revision mode"""
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
sub_id = get_subscription_id(cmd.cli_ctx)
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/functions?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
container_app_name,
cls.api_version)

r = send_raw_request(cmd.cli_ctx, "GET", request_url)
return r.json()

@classmethod
def get_function(cls, cmd, resource_group_name, container_app_name, function_name):
"""Get a specific function for a container app in single revision mode"""
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
sub_id = get_subscription_id(cmd.cli_ctx)
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerApps/{}/functions/{}?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
container_app_name,
function_name,
cls.api_version)

r = send_raw_request(cmd.cli_ctx, "GET", request_url)
return r.json()


class DaprComponentResiliencyPreviewClient():
api_version = PREVIEW_API_VERSION

Expand Down Expand Up @@ -1698,3 +1770,79 @@ def remove(cls, cmd, resource_group_name, environment_name):
if r.status_code == 202:
operation_url = r.headers.get(HEADER_LOCATION)
poll_results(cmd, operation_url)

class ContainerAppFunctionsPreviewClient:
api_version = PREVIEW_API_VERSION

@classmethod
def list_function_keys(cls, cmd, resource_group_name, name, function_name):
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
sub_id = get_subscription_id(cmd.cli_ctx)
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerapps/{}/functions/{}/listkeys?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
name,
function_name,
cls.api_version)

r = send_raw_request(cmd.cli_ctx, "POST", request_url)
return r.json()

@classmethod
def update_function_keys(cls, cmd, resource_group_name, name, function_name, key_name, key_value=None):
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
sub_id = get_subscription_id(cmd.cli_ctx)
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerapps/{}/functions/{}/keys/{}?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
name,
function_name,
key_name,
cls.api_version)

body = {}
if key_value:
body["value"] = key_value

r = send_raw_request(cmd.cli_ctx, "PUT", request_url, body=json.dumps(body))
return r.json()

@classmethod
def list_host_keys(cls, cmd, resource_group_name, name):
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
sub_id = get_subscription_id(cmd.cli_ctx)
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerapps/{}/host/default/listkeys?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
name,
cls.api_version)

r = send_raw_request(cmd.cli_ctx, "POST", request_url)
return r.json()

@classmethod
def update_host_keys(cls, cmd, resource_group_name, name, key_type, key_name, key_value=None):
management_hostname = cmd.cli_ctx.cloud.endpoints.resource_manager
sub_id = get_subscription_id(cmd.cli_ctx)
url_fmt = "{}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.App/containerapps/{}/host/default/{}/{}?api-version={}"
request_url = url_fmt.format(
management_hostname.strip('/'),
sub_id,
resource_group_name,
name,
key_type,
key_name,
cls.api_version)

body = {}
if key_value:
body["value"] = key_value

r = send_raw_request(cmd.cli_ctx, "PUT", request_url, body=json.dumps(body))
return r.json()
78 changes: 77 additions & 1 deletion src/containerapp/azext_containerapp/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@
az containerapp up -n my-containerapp --image my-app:v1.0 --kind functionapp
"""


helps['containerapp replica count'] = """
type: command
short-summary: Count of a container app's replica(s)
Expand All @@ -179,6 +178,83 @@
az containerapp replica count -n my-containerapp -g MyResourceGroup
"""

helps['containerapp function'] = """
type: group
short-summary: Commands related to Azure Function on Azure Container Apps.
"""

helps['containerapp function list'] = """
type: command
short-summary: List all functions in a container app or a specific revision. (pass --revisionName parameter)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
short-summary: List all functions in a container app or a specific revision. (pass --revisionName parameter)
short-summary: List all functions in an Azure Functions on Azure Container Apps.

Current summary seems to convey that the --revisionName parameter is mandatory, which is not true. Let's remove revision-specific help command, similar to other commands like az containerapp replica count.

long-summary: |
revisionName is required only if Container App active Revision Mode is setup in Multiple Revision Mode. (Default: Single Revision Mode)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
revisionName is required only if Container App active Revision Mode is setup in Multiple Revision Mode. (Default: Single Revision Mode)
--revision is required if the
Suggested change
revisionName is required only if Container App active Revision Mode is setup in Multiple Revision Mode. (Default: Single Revision Mode)
--revision is required only if the app is not in single revision mode.

We have multiple and labelled revision mode, so this statement will be simpler.

Run to check activerevisionmode: az containerapp show -n my-containerapp -g MyResourceGroup --query properties.configuration.activeRevisionsMode

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Run to check activerevisionmode: az containerapp show -n my-containerapp -g MyResourceGroup --query properties.configuration.activeRevisionsMode
To check the active revisions mode, run the following command: az containerapp show -n MyContainerApp -g MyResourceGroup --query properties.configuration.activeRevisionsMode

examples:
- name: List all functions in a container app. (single active revision mode)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- name: List all functions in a container app. (single active revision mode)
- name: List all functions in an Azure Functions on Azure Container Apps (single revision mode)

text: |
az containerapp function list -n my-containerapp -g MyResourceGroup

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
az containerapp function list -n my-containerapp -g MyResourceGroup
az containerapp function list -n MyContainerApp -g MyResourceGroup

- name: List all functions for a specific revision
text: |
az containerapp function list -n my-containerapp -g MyResourceGroup --revision-name MyRevision

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
az containerapp function list -n my-containerapp -g MyResourceGroup --revision-name MyRevision
az containerapp function list -n MyContainerApp -g MyResourceGroup --revision MyRevision

"""

helps['containerapp function show'] = """
type: command
short-summary: Show details of a specific function in a container app or a specific revision within app. (pass --revisionName parameter)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
short-summary: Show details of a specific function in a container app or a specific revision within app. (pass --revisionName parameter)
short-summary: Get details of a function in an Azure Functions on Azure Container Apps.

long-summary: |
revisionName is required only if Container App active Revision Mode is setup in Multiple Revision Mode. (Default: Single Revision Mode)
Run to check activerevisionmode: az containerapp show -n my-containerapp -g MyResourceGroup --query properties.configuration.activeRevisionsMode
Comment on lines +205 to +206

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment from list command

examples:
- name: Show details of a function in a container app. (single active revision mode)
text: |
az containerapp function show -n my-containerapp -g MyResourceGroup --function-name MyFunction
- name: Show details of a function for a specific revision
text: |
az containerapp function show -n my-containerapp -g MyResourceGroup --function-name MyFunction --revision-name MyRevision
"""

helps['containerapp function list-keys'] = """
type: command
short-summary: List function keys for a specific function in a container app.
examples:
- name: List function keys for a specific function
text: |
az containerapp function list-keys -n my-containerapp -g MyResourceGroup --revision MyContainerappRevision --function-name MyFunctionName
"""

helps['containerapp function update-keys'] = """
type: command
short-summary: Update function keys for a specific function in a container app.
examples:
- name: Update a function key for a specific function
text: |
az containerapp function update-keys -n my-containerapp -g MyResourceGroup --revision MyContainerappRevision --function-name MyFunctionName --key-name MyKeyName --key-value MyKeyValue
"""

helps['containerapp function list-hostkeys'] = """
type: command
short-summary: List host keys for a container app.
examples:
- name: List host keys for a container app
text: |
az containerapp function list-hostkeys -n my-containerapp -g MyResourceGroup --revision MyContainerappRevision
"""

helps['containerapp function update-hostkeys'] = """
type: command
short-summary: Update host keys for a container app.
examples:
- name: Update a host key for a container app with function key type
text: |
az containerapp function update-hostkeys -n my-containerapp -g MyResourceGroup --revision MyContainerappRevision --key-name MyKeyName --key-value MyKeyValue --key-type functionKeys
- name: Update a host key for a container app with master key type
text: |
az containerapp function update-hostkeys -n my-containerapp -g MyResourceGroup --revision MyContainerappRevision --key-name MyKeyName --key-value MyKeyValue --key-type masterKey
- name: Update a host key for a container app with system key type
text: |
az containerapp function update-hostkeys -n my-containerapp -g MyResourceGroup --revision MyContainerappRevision --key-name MyKeyName --key-value MyKeyValue --key-type systemKeys
"""

# Environment Commands
helps['containerapp env'] = """
type: group
Expand Down
30 changes: 30 additions & 0 deletions src/containerapp/azext_containerapp/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,3 +530,33 @@ def load_arguments(self, _):
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.")
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.")
c.argument('header_count_limit', options_list=['--header-count-limit'], type=int, help="Limit of http headers per request. Default 100, minimum 1.")

with self.argument_context('containerapp function') as c:
c.argument('resource_group_name', arg_type=resource_group_name_type, id_part=None)
c.argument('name', options_list=['--name', '-n'], help="The name of the Container App.")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
c.argument('name', options_list=['--name', '-n'], help="The name of the Container App.")
c.argument('name', options_list=['--name', '-n'], help="The name of the Azure Functions on Azure Container Apps.")


with self.argument_context('containerapp function list') as c:
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.")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parameter should just be --revision, following convention from other commands

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


with self.argument_context('containerapp function show') as c:
c.argument('function_name', options_list=['--function-name', '-f'], help="The name of the function to show details for.")
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.")

with self.argument_context('containerapp function list-keys') as c:
c.argument('revision', options_list=['--revision'], help="The name of the container app revision.")
c.argument('function_name', options_list=['--function-name'], help="The name of the function.")

with self.argument_context('containerapp function update-keys') as c:
c.argument('revision', options_list=['--revision'], help="The name of the container app revision.")
c.argument('function_name', options_list=['--function-name'], help="The name of the function.")
c.argument('key_name', options_list=['--key-name'], help="The name of the key to update.")
c.argument('key_value', options_list=['--key-value'], help="The value of the key to update.")

with self.argument_context('containerapp function list-hostkeys') as c:
c.argument('revision', options_list=['--revision'], help="The name of the container app revision.")

with self.argument_context('containerapp function update-hostkeys') as c:
c.argument('revision', options_list=['--revision'], help="The name of the container app revision.")
c.argument('key_name', options_list=['--key-name'], help="The name of the host key to update.")
c.argument('key_value', options_list=['--key-value'], help="The value of the host key to update.")
c.argument('key_type', options_list=['--key-type'], arg_type=get_enum_type(['functionKeys', 'masterKey', 'systemKeys']), help="The type of the host key.")
10 changes: 10 additions & 0 deletions src/containerapp/azext_containerapp/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ def load_command_table(self, args):
g.custom_command('list', 'list_replicas')
g.custom_command('count', 'count_replicas', is_preview=True)

with self.command_group('containerapp function', is_preview=True) as g:
g.custom_command('list', 'list_containerapp_functions')
g.custom_show_command('show', 'show_containerapp_function')

with self.command_group('containerapp env') as g:
g.custom_show_command('show', 'show_managed_environment')
g.custom_command('list', 'list_managed_environments')
Expand Down Expand Up @@ -297,3 +301,9 @@ def load_command_table(self, args):
g.custom_command('add', 'add_environment_premium_ingress')
g.custom_command('update', 'update_environment_premium_ingress')
g.custom_command('remove', 'remove_environment_premium_ingress', confirmation=True)

with self.command_group('containerapp function') as g:
g.custom_command('list-keys', 'list_containerapp_function_keys')
g.custom_command('update-keys', 'update_containerapp_function_keys')
g.custom_command('list-hostkeys', 'list_containerapp_function_hostkeys')
g.custom_command('update-hostkeys', 'update_containerapp_function_hostkeys')
Loading
Loading