Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[containerapp] suspend/resume a container apps job #8270

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions src/containerapp/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Release History
===============
upcoming
++++++
* 'az containerapp job suspend': Support command to suspend a container apps job
Copy link
Contributor

Choose a reason for hiding this comment

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

Please sync the main branch and move these to the latest upcoming part

* 'az containerapp job resume': Support command to resume a container apps job
* 'az containerapp create': Fix Role assignment error when the default Azure Container Registry could not be found
* Upgrade api-version to 2024-10-02-preview
* 'az containerapp create/update': `--yaml` support property pollingInterval and cooldownPeriod
Expand Down
32 changes: 32 additions & 0 deletions src/containerapp/azext_containerapp/_clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,38 @@ def get_auth_token(cls, cmd, resource_group_name, name):
r = send_raw_request(cmd.cli_ctx, "POST", request_url)
return r.json()

@classmethod
def suspend(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/jobs/{}/suspend?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)
if r.status_code == 202:
return
Copy link
Contributor

Choose a reason for hiding this comment

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

handle other response codes as well. For example, if Job is not found, then we would return 404 from the RP, but in this case we would not return the correct information.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added!

Copy link
Contributor

Choose a reason for hiding this comment

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

In the send_raw_request(cmd.cli_ctx, "POST", request_url) it throw error when return 4xx. So not need to handle it here specifically.
We need to have test to cover this case and check the error message.


@classmethod
def resume(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/jobs/{}/resume?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)
if r.status_code == 202:
return


class ContainerAppsResiliencyPreviewClient():
api_version = PREVIEW_API_VERSION
Expand Down
18 changes: 18 additions & 0 deletions src/containerapp/azext_containerapp/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,24 @@
text: az containerapp job stop -n my-containerapp-job -g MyResourceGroup --execution-name-list MyContainerAppJob-66v9xh0,MyContainerAppJob-66v9xh1
"""

helps['containerapp job suspend'] = """
type: command
short-summary: Suspend a Container Apps Job.
examples:
- name: Suspend a job.
text: |
az containerapp job suspend -n my-containerapp-job -g MyResourceGroup
"""

helps['containerapp job resume'] = """
type: command
short-summary: Resume a Container Apps Job.
examples:
- name: Resume a job.
text: |
az containerapp job resume -n my-containerapp-job -g MyResourceGroup
"""

# Certificates Commands
helps['containerapp env certificate'] = """
type: group
Expand Down
8 changes: 8 additions & 0 deletions src/containerapp/azext_containerapp/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,14 @@ def load_arguments(self, _):
with self.argument_context('containerapp job registry') as c:
c.argument('identity', help="The managed identity with which to authenticate to the Azure Container Registry (instead of username/password). Use 'system' for a system-defined identity, Use 'system-environment' for an environment level system-defined identity or a resource id for a user-defined environment/containerapp level identity. The managed identity should have been assigned acrpull permissions on the ACR before deployment (use 'az role assignment create --role acrpull ...').")

with self.argument_context('containerapp job suspend') as c:
c.argument('name', name_type, id_part=None, help="The name of the Containerapp job.")
c.argument('resource_group_name', arg_type=resource_group_name_type, id_part=None)

with self.argument_context('containerapp job resume') as c:
c.argument('name', name_type, id_part=None, help="The name of the Containerapp job.")
c.argument('resource_group_name', arg_type=resource_group_name_type, id_part=None)
Comment on lines +398 to +404
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you don't need to add these params, because they can inherit the params from az containerapp job


with self.argument_context('containerapp env dotnet-component') as c:
c.argument('dotnet_component_name', options_list=['--name', '-n'], help="The DotNet component name.")
c.argument('environment_name', options_list=['--environment'], help="The environment name.")
Expand Down
6 changes: 6 additions & 0 deletions src/containerapp/azext_containerapp/_sdk_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8354,6 +8354,9 @@ class ContainerAppsJob(TrackedResource): # pylint: disable=too-many-instance-at
:ivar provisioning_state: Provisioning state of the Container Apps Job. Known values are:
"InProgress", "Succeeded", "Failed", "Canceled", and "Deleting".
:vartype provisioning_state: str or ~azure.mgmt.appcontainers.models.JobProvisioningState
:ivar running_status: Running status of the Container Apps Job. Known values are:
"Progressing", "Suspended" and "Ready".
:vartype running_status: str or ~azure.mgmt.appcontainers.models.JobRunningState
:ivar environment_id: Resource ID of environment.
:vartype environment_id: str
:ivar workload_profile_name: Workload profile name to pin for container apps job execution.
Expand All @@ -8375,6 +8378,7 @@ class ContainerAppsJob(TrackedResource): # pylint: disable=too-many-instance-at
"system_data": {"readonly": True},
"location": {"required": True},
"provisioning_state": {"readonly": True},
"running_status": {"readonly": True},
"outbound_ip_addresses": {"readonly": True},
"event_stream_endpoint": {"readonly": True},
}
Expand All @@ -8389,6 +8393,7 @@ class ContainerAppsJob(TrackedResource): # pylint: disable=too-many-instance-at
"extended_location": {"key": "extendedLocation", "type": "ExtendedLocation"},
"identity": {"key": "identity", "type": "ManagedServiceIdentity"},
"provisioning_state": {"key": "properties.provisioningState", "type": "str"},
"running_status": {"key": "properties.runningStatus", "type": "str"},
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add YAML test to cover it. And rerun all tests relate to az containerapp job create/update --yaml

Copy link
Contributor

Choose a reason for hiding this comment

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

It is a readonly property, we cannot update it with az containerapp job create/update --yaml, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

Why you need to update this class?
In fact az containerapp job create/update --yaml is using class Job, not this one. I think you don't need to update this file.

"environment_id": {"key": "properties.environmentId", "type": "str"},
"workload_profile_name": {"key": "properties.workloadProfileName", "type": "str"},
"configuration": {"key": "properties.configuration", "type": "JobConfiguration"},
Expand Down Expand Up @@ -8433,6 +8438,7 @@ def __init__(
self.extended_location = extended_location
self.identity = identity
self.provisioning_state = None
self.running_status = None
self.environment_id = environment_id
self.workload_profile_name = workload_profile_name
self.configuration = configuration
Expand Down
2 changes: 2 additions & 0 deletions src/containerapp/azext_containerapp/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ def load_command_table(self, args):
g.custom_command('create', 'create_containerappsjob', supports_no_wait=True, exception_handler=ex_handler_factory(), transform=transform_sensitive_values)
g.custom_command('update', 'update_containerappsjob', supports_no_wait=True, exception_handler=ex_handler_factory(), transform=transform_sensitive_values)
g.custom_command('delete', 'delete_containerappsjob', supports_no_wait=True, confirmation=True, exception_handler=ex_handler_factory())
g.custom_command('suspend', 'suspend_containerappsjob', supports_no_wait=True, exception_handler=ex_handler_factory())
Copy link
Contributor

Choose a reason for hiding this comment

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

It would better to ask the customer to confirm action like az containerapp job delete?
Recommedn to add confirmation=True

g.custom_command('resume', 'resume_containerappsjob', supports_no_wait=True, exception_handler=ex_handler_factory())

with self.command_group('containerapp job registry', is_preview=True) as g:
g.custom_command('set', 'set_registry_job', exception_handler=ex_handler_factory())
Expand Down
27 changes: 27 additions & 0 deletions src/containerapp/azext_containerapp/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -1017,6 +1017,33 @@ def delete_containerappsjob(cmd, name, resource_group_name, no_wait=False):
return containerapp_job_decorator.delete()


def suspend_containerappsjob(cmd, name, resource_group_name):
raw_parameters = locals()
containerapp_job_decorator = ContainerAppJobDecorator(
cmd=cmd,
client=ContainerAppsJobPreviewClient,
raw_parameters=raw_parameters,
models=CONTAINER_APPS_SDK_MODELS
)
containerapp_job_decorator.validate_subscription_registered(CONTAINER_APPS_RP)

return ContainerAppsJobPreviewClient.suspend(cmd=cmd, resource_group_name=resource_group_name, name=name)
Copy link
Contributor

@Greedygre Greedygre Nov 22, 2024

Choose a reason for hiding this comment

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

Please use the containerapp_job_suspend_decorator to execute containerapp_job_suspend_decorator.suspend()
You can refer : class ContainerAppPreviewListDecorator(BaseContainerAppDecorator) to create
class ContainerAppJobSuspendDecorator(ContainerAppJobDecorator)



def resume_containerappsjob(cmd, name, resource_group_name):
raw_parameters = locals()
containerapp_job_decorator = ContainerAppJobDecorator(
cmd=cmd,
client=ContainerAppsJobPreviewClient,
raw_parameters=raw_parameters,
models=CONTAINER_APPS_SDK_MODELS
)

containerapp_job_decorator.validate_subscription_registered(CONTAINER_APPS_RP)

return ContainerAppsJobPreviewClient.resume(cmd=cmd, resource_group_name=resource_group_name, name=name)
Copy link
Contributor

Choose a reason for hiding this comment

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

same as above.



def create_or_update_github_action(cmd,
name,
resource_group_name,
Expand Down
Loading
Loading