Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 0 additions & 99 deletions src/containerapp/azext_containerapp/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -2337,102 +2337,3 @@
text: |
az containerapp label-history show -n my-containerapp -g MyResourceGroup --label LabelName
"""

helps['containerapp env http-route-config'] = """
type: group
short-summary: Commands to manage environment level http routing.
"""

helps['containerapp env http-route-config list'] = """
type: command
short-summary: List the http route configs in the environment.
examples:
- name: List the http route configs in the environment.
text: |
az containerapp env http-route-config list -g MyResourceGroup -n MyEnvironment
"""

helps['containerapp env http-route-config create'] = """
type: command
short-summary: Create a new http route config.
examples:
- name: Create a new route from a yaml file.
text: |
az containerapp env http-route-config create -g MyResourceGroup -n MyEnvironment -r configname --yaml config.yaml
"""

helps['containerapp env http-route-config update'] = """
type: command
short-summary: Update a http route config.
examples:
- name: Update a route in the environment from a yaml file.
text: |
az containerapp env http-route-config update -g MyResourceGroup -n MyEnvironment -r configname --yaml config.yaml
"""

helps['containerapp env http-route-config show'] = """
type: command
short-summary: Show a http route config.
examples:
- name: Show a route in the environment.
text: |
az containerapp env http-route-config show -g MyResourceGroup -n MyEnvironment -r configname
"""

helps['containerapp env http-route-config delete'] = """
type: command
short-summary: Delete a http route config.
examples:
- name: Delete a route from the environment.
text: |
az containerapp env http-route-config delete -g MyResourceGroup -n MyEnvironment -r configname
"""

helps['containerapp env premium-ingress show'] = """
type: command
short-summary: Show the premium ingress settings for the environment.
examples:
- name: Show the premium ingress settings for the environment.
text: |
az containerapp env premium-ingress show -g MyResourceGroup -n MyEnvironment
"""

helps['containerapp env premium-ingress'] = """
type: group
short-summary: Configure premium ingress settings for the environment.
long-summary: |
Premium ingress settings apply to all applications in the environment. They allow moving the ingress instances to a workload profile and scaling them beyond the system defaults to enable high traffic workloads. Other settings include request idle timeouts, header count limits, and the termination grace period.
examples:
- name: Enable premium ingress for the environment.
text: |
az containerapp env premium-ingress add -g MyResourceGroup -n MyEnvironment -w WorkloadProfileName
"""

helps['containerapp env premium-ingress add'] = """
type: command
short-summary: Enable the premium ingress settings for the environment.
long-summary: |
Unspecified optional parameters will be cleared from any existing configuration.
examples:
- name: Add the premium ingress settings for the environment.
text: |
az containerapp env premium-ingress add -g MyResourceGroup -n MyEnvironment -w WorkloadProfileName
"""

helps['containerapp env premium-ingress update'] = """
type: command
short-summary: Update the premium ingress settings for the environment.
examples:
- name: Update the workload profile used for premium ingress.
text: |
az containerapp env premium-ingress update -g MyResourceGroup -n MyEnvironment -w WorkloadProfileName
"""

helps['containerapp env premium-ingress remove'] = """
type: command
short-summary: Remove the ingress settings and restores the system to default values.
examples:
- name: Reset the ingress settings for the environment to its default values
text: |
az containerapp env premium-ingress remove -g MyResourceGroup -n MyEnvironment
"""
16 changes: 0 additions & 16 deletions src/containerapp/azext_containerapp/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,6 @@ def load_arguments(self, _):
c.argument('logs_dynamic_json_columns', options_list=['--logs-dynamic-json-columns', '-j'], arg_type=get_three_state_flag(),
help='Boolean indicating whether to parse json string log into dynamic json columns. Only work for destination log-analytics.', is_preview=True)

# HttpRouteConfig
with self.argument_context('containerapp env http-route-config') as c:
c.argument('http_route_config_name', options_list=['--http-route-config-name', '-r'], help="The name of the http route configuration.")
c.argument('yaml', help="The path to the YAML input file.")
c.argument('name', id_part=None)

# Telemetry
with self.argument_context('containerapp env telemetry') as c:
c.argument('name', id_part=None)
Expand Down Expand Up @@ -526,13 +520,3 @@ def load_arguments(self, _):
with self.argument_context('containerapp revision set-mode') as c:
c.argument('mode', arg_type=get_enum_type(['single', 'multiple', 'labels']), help="The active revisions mode for the container app.")
c.argument('target_label', help="The label to apply to new revisions. Required for revision mode 'labels'.", is_preview=True)

with self.argument_context('containerapp env premium-ingress') 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 managed environment.")
c.argument('workload_profile_name', options_list=['--workload-profile-name', '-w'], help="The workload profile to run ingress replicas on. This profile must not be shared with any container app or job.")
c.argument('min_replicas', options_list=['--min-replicas'], type=int, deprecate_info=c.deprecate(hide=True, expiration='2.78.0'), help="The workload profile minimum instances is used instead.")
c.argument('max_replicas', options_list=['--max-replicas'], type=int, deprecate_info=c.deprecate(hide=True, expiration='2.78.0'), help="The workload profile maximum instances is used instead.")
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.")
13 changes: 0 additions & 13 deletions src/containerapp/azext_containerapp/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,6 @@ def load_command_table(self, args):
g.custom_command('delete', 'delete_managed_environment', supports_no_wait=True, confirmation=True, exception_handler=ex_handler_factory())
g.custom_command('update', 'update_managed_environment', supports_no_wait=True, exception_handler=ex_handler_factory())

with self.command_group('containerapp env http-route-config', is_preview=True) as g:
Copy link
Contributor

@Greedygre Greedygre Oct 2, 2025

Choose a reason for hiding this comment

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

To avoid breaking change, we can remove the is_preview=True in extension first.
Then after azure-cli release, we update "azext.minCliCoreVersion": <azure-cli-version> in azext_metadata.json first, then remove these GA commands in extension.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

what if we just wait to merge this until after the azure-cli release?

Copy link
Contributor

@Greedygre Greedygre Oct 2, 2025

Choose a reason for hiding this comment

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

@Tratcher It depends on if you mind customer will see the Preview tag if they already install latest containerapp extension and azure-cli version.
If you care the Preview Tag, it should separate to 2 PR.

image

Copy link
Contributor

@Greedygre Greedygre Oct 2, 2025

Choose a reason for hiding this comment

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

But yes we can just wait to merge until after the azure-cli release.
Besides I will discuss the azure-cli-extension containerapp module release plan for ignite with co-workers after holiday to double check if we have plan to release a new version to separate these.

g.custom_show_command('show', 'show_http_route_config')
g.custom_command('list', 'list_http_route_configs')
g.custom_command('create', 'create_http_route_config', exception_handler=ex_handler_factory())
g.custom_command('update', 'update_http_route_config', exception_handler=ex_handler_factory())
g.custom_command('delete', 'delete_http_route_config', confirmation=True, exception_handler=ex_handler_factory())

with self.command_group('containerapp job') as g:
g.custom_show_command('show', 'show_containerappsjob')
g.custom_command('list', 'list_containerappsjob')
Expand Down Expand Up @@ -294,9 +287,3 @@ def load_command_table(self, args):
with self.command_group('containerapp revision label') as g:
g.custom_command('add', 'add_revision_label')
g.custom_command('remove', 'remove_revision_label')

with self.command_group('containerapp env premium-ingress', is_preview=True) as g:
g.custom_show_command('show', 'show_environment_premium_ingress')
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)
159 changes: 0 additions & 159 deletions src/containerapp/azext_containerapp/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@
SessionCustomContainerPreviewClient,
DotNetComponentPreviewClient,
MaintenanceConfigPreviewClient,
HttpRouteConfigPreviewClient,
LabelHistoryPreviewClient
)
from ._dev_service_utils import DevServiceUtils
Expand Down Expand Up @@ -3633,61 +3632,6 @@ def containerapp_debug(cmd, resource_group_name, name, container=None, revision=
logger.info("Caught KeyboardInterrupt. Sending ctrl+c to server")
conn.send(SSH_CTRL_C_MSG)


def create_http_route_config(cmd, resource_group_name, name, http_route_config_name, yaml):
_validate_subscription_registered(cmd, CONTAINER_APPS_RP)
yaml_http_route_config = load_yaml_file(yaml)
# check if the type is dict
if not isinstance(yaml_http_route_config, dict):
raise ValidationError('Invalid YAML provided. Please see https://aka.ms/azure-container-apps-yaml for a valid YAML spec.')

http_route_config_envelope = {"properties": yaml_http_route_config}

try:
return HttpRouteConfigPreviewClient.create(cmd, resource_group_name, name, http_route_config_name, http_route_config_envelope)
except Exception as e:
handle_raw_exception(e)


def update_http_route_config(cmd, resource_group_name, name, http_route_config_name, yaml):
_validate_subscription_registered(cmd, CONTAINER_APPS_RP)
yaml_http_route_config = load_yaml_file(yaml)
# check if the type is dict
if not isinstance(yaml_http_route_config, dict):
raise ValidationError('Invalid YAML provided. Please see https://aka.ms/azure-container-apps-yaml for a valid YAML spec.')

http_route_config_envelope = {"properties": yaml_http_route_config}

try:
return HttpRouteConfigPreviewClient.update(cmd, resource_group_name, name, http_route_config_name, http_route_config_envelope)
except Exception as e:
handle_raw_exception(e)


def list_http_route_configs(cmd, resource_group_name, name):
_validate_subscription_registered(cmd, CONTAINER_APPS_RP)
try:
return HttpRouteConfigPreviewClient.list(cmd, resource_group_name, name)
except Exception as e:
handle_raw_exception(e)


def show_http_route_config(cmd, resource_group_name, name, http_route_config_name):
_validate_subscription_registered(cmd, CONTAINER_APPS_RP)
try:
return HttpRouteConfigPreviewClient.show(cmd, resource_group_name, name, http_route_config_name)
except Exception as e:
handle_raw_exception(e)


def delete_http_route_config(cmd, resource_group_name, name, http_route_config_name):
_validate_subscription_registered(cmd, CONTAINER_APPS_RP)
try:
return HttpRouteConfigPreviewClient.delete(cmd, resource_group_name, name, http_route_config_name)
except Exception as e:
handle_raw_exception(e)


def list_label_history(cmd, resource_group_name, name):
_validate_subscription_registered(cmd, CONTAINER_APPS_RP)
try:
Expand Down Expand Up @@ -3857,106 +3801,3 @@ def remove_revision_label(cmd, resource_group_name, name, label, no_wait=False):
return r['properties']['configuration']['ingress']['traffic']
except Exception as e:
handle_raw_exception(e)


def show_environment_premium_ingress(cmd, name, resource_group_name):
_validate_subscription_registered(cmd, CONTAINER_APPS_RP)

try:
env = ManagedEnvironmentPreviewClient.show(cmd, resource_group_name, name)
ingress_config = safe_get(env, "properties", "ingressConfiguration")
if not ingress_config:
return {"message": "No premium ingress configuration found for this environment, using default values."}

return ingress_config
except Exception as e:
handle_raw_exception(e)


def add_environment_premium_ingress(cmd, name, resource_group_name, workload_profile_name, min_replicas=None, max_replicas=None, termination_grace_period=None, request_idle_timeout=None, header_count_limit=None, no_wait=False):
_validate_subscription_registered(cmd, CONTAINER_APPS_RP)

try:
ManagedEnvironmentPreviewClient.show(cmd, resource_group_name, name)
env_patch = {}
ingress_config = {}
safe_set(env_patch, "properties", "ingressConfiguration", value=ingress_config)

# Required
ingress_config["workloadProfileName"] = workload_profile_name
# Optional, remove if None
ingress_config["terminationGracePeriodSeconds"] = termination_grace_period
ingress_config["requestIdleTimeout"] = request_idle_timeout
ingress_config["headerCountLimit"] = header_count_limit

result = ManagedEnvironmentPreviewClient.update(
cmd=cmd,
resource_group_name=resource_group_name,
name=name,
managed_environment_envelope=env_patch,
no_wait=no_wait
)

return safe_get(result, "properties", "ingressConfiguration")

except Exception as e:
handle_raw_exception(e)


def update_environment_premium_ingress(cmd, name, resource_group_name, workload_profile_name=None, min_replicas=None, max_replicas=None, termination_grace_period=None, request_idle_timeout=None, header_count_limit=None, no_wait=False):
_validate_subscription_registered(cmd, CONTAINER_APPS_RP)

try:
ManagedEnvironmentPreviewClient.show(cmd, resource_group_name, name)
env_patch = {}
ingress_config = {}

if workload_profile_name is not None:
ingress_config["workloadProfileName"] = workload_profile_name
if termination_grace_period is not None:
ingress_config["terminationGracePeriodSeconds"] = termination_grace_period
if request_idle_timeout is not None:
ingress_config["requestIdleTimeout"] = request_idle_timeout
if header_count_limit is not None:
ingress_config["headerCountLimit"] = header_count_limit

# Only add ingressConfiguration to the patch if any values were specified
if ingress_config:
safe_set(env_patch, "properties", "ingressConfiguration", value=ingress_config)
else:
return {"message": "No changes specified for premium ingress configuration"}

# Update the environment with the patched ingress configuration
result = ManagedEnvironmentPreviewClient.update(
cmd=cmd,
resource_group_name=resource_group_name,
name=name,
managed_environment_envelope=env_patch,
no_wait=no_wait
)

return safe_get(result, "properties", "ingressConfiguration")

except Exception as e:
handle_raw_exception(e)


def remove_environment_premium_ingress(cmd, name, resource_group_name, no_wait=False):
_validate_subscription_registered(cmd, CONTAINER_APPS_RP)

try:
ManagedEnvironmentPreviewClient.show(cmd, resource_group_name, name)
env_patch = {}
# Remove the whole section to restore defaults
safe_set(env_patch, "properties", "ingressConfiguration", value=None)

ManagedEnvironmentPreviewClient.update(
cmd=cmd,
resource_group_name=resource_group_name,
name=name,
managed_environment_envelope=env_patch,
no_wait=no_wait
)

except Exception as e:
handle_raw_exception(e)
Loading
Loading