Skip to content

Commit

Permalink
[fleet] add fleet auto upgrade profile commands (#7887)
Browse files Browse the repository at this point in the history
* add fleet auto upgrade profile commands

* style

* update sdk and tests

* fix ex

* fix help

* add validator test

* update validator test

* fix linter and tests

* fix style

* inc version

* inc version

---------

Co-authored-by: pdaru <[email protected]>
  • Loading branch information
pdaru and pdaru authored Sep 27, 2024
1 parent 5140e4b commit 9f42ff0
Show file tree
Hide file tree
Showing 30 changed files with 2,493 additions and 1,779 deletions.
4 changes: 4 additions & 0 deletions src/fleet/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,7 @@ Release History
++++++
* Added missing help text
* Removed dependency on msrestazure library

1.3.0
++++++
* Add fleet autoupgradeprofile commands
4 changes: 4 additions & 0 deletions src/fleet/azext_fleet/_client_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,7 @@ def cf_fleet_update_strategies(cli_ctx, *_):
def get_resource_groups_client(cli_ctx, subscription_id=None):
return get_mgmt_service_client(
cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES, subscription_id=subscription_id).resource_groups


def cf_auto_upgrade_profiles(cli_ctx, *_):
return get_container_service_client(cli_ctx).auto_upgrade_profiles
45 changes: 45 additions & 0 deletions src/fleet/azext_fleet/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,3 +340,48 @@
short-summary: Wait for a update strategy resource to reach a desired state.
long-summary: If an operation on an update strategy was interrupted or was started with `--no-wait`, use this command to wait for it to complete.
"""

helps['fleet autoupgradeprofile'] = """
type: group
short-summary: Commands to manage auto upgrade profiles.
"""

helps['fleet autoupgradeprofile create'] = """
type: command
short-summary: Creates or updates an auto upgrade profile.
examples:
- name: Create an auto upgrade profile with channel 'Rapid' and disabled by default.
text: az fleet autoupgradeprofile create -g MyFleetResourceGroup -f MyFleetName -n MyAutoUpgradeProfileName -c Rapid --disabled
- name: Create an auto upgrade profile with channel 'NodeImage'.
text: az fleet autoupgradeprofile create -g MyFleetResourceGroup -f MyFleetName -n MyAutoUpgradeProfileName -c NodeImage
"""

helps['fleet autoupgradeprofile delete'] = """
type: command
short-summary: Deletes an auto upgrade profile.
examples:
- name: Delete an auto upgrade profile.
text: az fleet autoupgradeprofile delete -g MyFleetResourceGroup -f MyFleetName -n MyAutoUpgradeProfileName
"""

helps['fleet autoupgradeprofile show'] = """
type: command
short-summary: Shows an auto upgrade profile.
examples:
- name: Show the details of an auto upgrade profile.
text: az fleet autoupgradeprofile show -g MyFleetResourceGroup -f MyFleetName -n MyAutoUpgradeProfileName
"""

helps['fleet autoupgradeprofile list'] = """
type: command
short-summary: Lists all auto upgrade profiles for a given fleet.
examples:
- name: List auto upgrade profiles of a fleet.
text: az fleet autoupgradeprofile list -g MyFleetResourceGroup -f MyFleetName
"""

helps['fleet autoupgradeprofile wait'] = """
type: command
short-summary: Wait for an auto upgrade resource to reach a desired state.
long-summary: If an operation on an auto upgrade profile was interrupted or was started with `--no-wait`, use this command to wait for it to complete.
"""
56 changes: 46 additions & 10 deletions src/fleet/azext_fleet/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,20 @@
get_three_state_flag
)
from azure.cli.core.commands.validators import get_default_location_from_resource_group
from azext_fleet._validators import validate_member_cluster_id, validate_kubernetes_version, validate_apiserver_subnet_id, validate_agent_subnet_id, validate_assign_identity, validate_update_strategy_name, validate_vm_size, validate_targets
from azext_fleet._validators import (
validate_member_cluster_id,
validate_kubernetes_version,
validate_apiserver_subnet_id,
validate_agent_subnet_id,
validate_assign_identity,
validate_update_strategy_name,
validate_vm_size,
validate_targets,
validate_update_strategy_id,
)


def load_arguments(self, _):

with self.argument_context('fleet') as c:
c.argument('name', options_list=['--name', '-n'], help='Specify the fleet name.')
c.argument('location', get_location_type(self.cli_ctx), validator=get_default_location_from_resource_group)
Expand All @@ -36,12 +45,15 @@ def load_arguments(self, _):

with self.argument_context('fleet update') as c:
c.argument('tags', tags_type)
c.argument('enable_managed_identity', arg_type=get_three_state_flag(), help='Enable system assigned managed identity (MSI) on the Fleet resource.')
c.argument('assign_identity', validator=validate_assign_identity, help='With --enable-managed-identity, enable user assigned managed identity (MSI) on the Fleet resource. Specify the existing user assigned identity resource.')
c.argument('enable_managed_identity', arg_type=get_three_state_flag(),
help='Enable system assigned managed identity (MSI) on the Fleet resource.')
c.argument('assign_identity', validator=validate_assign_identity,
help='With --enable-managed-identity, enable user assigned managed identity (MSI) on the Fleet resource. Specify the existing user assigned identity resource.')

with self.argument_context('fleet get-credentials') as c:
c.argument('context_name', options_list=['--context'], help='If specified, overwrite the default context name.')
c.argument('path', options_list=['--file', '-f'], type=file_type, completer=FilesCompleter(), default=os.path.join(os.path.expanduser('~'), '.kube', 'config'))
c.argument('path', options_list=['--file', '-f'], type=file_type, completer=FilesCompleter(),
default=os.path.join(os.path.expanduser('~'), '.kube', 'config'))

with self.argument_context('fleet member') as c:
c.argument('name', options_list=['--name', '-n'], help='Specify the fleet member name.')
Expand All @@ -61,16 +73,40 @@ def load_arguments(self, _):
with self.argument_context('fleet updaterun create') as c:
c.argument('upgrade_type', arg_type=get_enum_type(['Full', 'NodeImageOnly', 'ControlPlaneOnly']))
c.argument('kubernetes_version', validator=validate_kubernetes_version)
c.argument('node_image_selection', arg_type=get_enum_type(['Latest', 'Consistent']), help='Node Image Selection is an option that lets you choose how your clusters\' nodes are upgraded')
c.argument('stages', type=file_type, completer=FilesCompleter(), help='Path to a json file that defines stages to upgrade a fleet. See examples for further reference.')
c.argument('update_strategy_name', validator=validate_update_strategy_name, help='The name of the update strategy to use for this update run. If not specified, the default update strategy will be used.')
c.argument('node_image_selection', arg_type=get_enum_type(['Latest', 'Consistent']),
help='Node Image Selection is an option that lets you choose how your clusters\' nodes are upgraded')
c.argument('stages', type=file_type, completer=FilesCompleter(),
help='Path to a json file that defines stages to upgrade a fleet. See examples for further reference.')
c.argument('update_strategy_name', validator=validate_update_strategy_name,
help='The name of the update strategy to use for this update run. If not specified, the default update strategy will be used.')

with self.argument_context('fleet updaterun skip', is_preview=True) as c:
c.argument('targets', nargs="+", validator=validate_targets, help='Space-separated list of targets to skip. Targets must be of the form `targetType:targetName` such as Group:MyGroup. Valid target types are: [`Member`, `Group`, `Stage`, `AfterStageWait`]. The target type is case-sensitive.', is_preview=True)
c.argument('targets', nargs="+", validator=validate_targets,
help='Space-separated list of targets to skip. Targets must be of the form `targetType:targetName` such as Group:MyGroup. Valid target types are: [`Member`, `Group`, `Stage`, `AfterStageWait`]. The target type is case-sensitive.',
is_preview=True)

with self.argument_context('fleet updatestrategy') as c:
c.argument('name', options_list=['--name', '-n'], help='Specify name for the fleet update strategy.')
c.argument('fleet_name', options_list=['--fleet-name', '-f'], help='Specify the fleet name.')

with self.argument_context('fleet updatestrategy create') as c:
c.argument('stages', type=file_type, completer=FilesCompleter(), help='Path to a json file that defines an update strategy.')
c.argument('stages', type=file_type, completer=FilesCompleter(),
help='Path to a json file that defines an update strategy.')

with self.argument_context('fleet autoupgradeprofile') as c:
c.argument('name', options_list=['--name', '-n'], help='Specify name for the auto upgrade profile.')
c.argument('fleet_name', options_list=['--fleet-name', '-f'], help='Specify the fleet name.')

with self.argument_context('fleet autoupgradeprofile create') as c:
c.argument('update_strategy_id', validator=validate_update_strategy_id,
help='The resource ID of the update strategy that the auto upgrade profile should follow.')
c.argument('channel', options_list=['--channel', '-c'], arg_type=get_enum_type(['Stable', 'Rapid', 'NodeImage']),
help='The auto upgrade channel type.')
c.argument('node_image_selection', arg_type=get_enum_type(['Latest', 'Consistent']),
help='Node Image Selection is an option that lets you choose how your clusters\' nodes are upgraded')
c.argument('disabled', action='store_true',
help='The disabled flag ensures auto upgrade profile does not run by default')

with self.argument_context('fleet autoupgradeprofile wait') as c:
c.argument('auto_upgrade_profile_name', options_list=['--auto-upgrade-profile-name', '--profile-name'],
help='Specify name for the auto upgrade profile.')
10 changes: 9 additions & 1 deletion src/fleet/azext_fleet/_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from azure.mgmt.core.tools import is_valid_resource_id


# https://github.com/Azure/azure-cli/blob/master/doc/authoring_command_modules/authoring_commands.md#supporting-name-or-id-parameters
def validate_member_cluster_id(namespace):
if not is_valid_resource_id(namespace.member_cluster_id):
raise InvalidArgumentValueError(
Expand Down Expand Up @@ -88,3 +87,12 @@ def _validate_target(target):
if parts[0] not in valid_keys:
raise InvalidArgumentValueError("Invalid target type, valid types are the following case-sensitive values:"
"'AfterStageWait', 'Group', 'Member', or 'Stage'.")


def validate_update_strategy_id(namespace):
update_strategy_id = namespace.update_strategy_id
if update_strategy_id is None:
return
if not is_valid_resource_id(update_strategy_id):
raise InvalidArgumentValueError(
"--update-strategy-id is not a valid Azure resource ID.")
22 changes: 21 additions & 1 deletion src/fleet/azext_fleet/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@

# pylint: disable=line-too-long
from azure.cli.core.commands import CliCommandType
from azext_fleet._client_factory import cf_fleets, cf_fleet_members, cf_update_runs, cf_fleet_update_strategies
from azext_fleet._client_factory import (
cf_fleets,
cf_fleet_members,
cf_update_runs,
cf_fleet_update_strategies,
cf_auto_upgrade_profiles
)


def load_command_table(self, _):
Expand Down Expand Up @@ -34,6 +40,12 @@ def load_command_table(self, _):
client_factory=cf_fleet_update_strategies
)

auto_upgrade_profiles_sdk = CliCommandType(
operations_tmpl="azext_fleet.vendored_sdks.operations._auto_upgrade_profiles_operations#AutoUpgradeProfilesOperations.{}",
operation_group="auto_upgrade_profiles",
client_factory=cf_auto_upgrade_profiles
)

# fleets command group
with self.command_group("fleet", fleets_sdk, client_factory=cf_fleets) as g:
g.custom_command("create", "create_fleet", supports_no_wait=True)
Expand Down Expand Up @@ -73,3 +85,11 @@ def load_command_table(self, _):
g.custom_command("list", "list_fleet_update_strategies")
g.custom_command("delete", "delete_fleet_update_strategy", supports_no_wait=True, confirmation=True)
g.wait_command("wait")

# auto upgrade profiles command group
with self.command_group("fleet autoupgradeprofile", auto_upgrade_profiles_sdk, client_factory=cf_auto_upgrade_profiles) as g:
g.custom_command("create", "create_auto_upgrade_profile", supports_no_wait=True)
g.custom_show_command("show", "show_auto_upgrade_profile")
g.custom_command("list", "list_auto_upgrade_profiles")
g.custom_command("delete", "delete_auto_upgrade_profile", supports_no_wait=True, confirmation=True)
g.wait_command("wait")
74 changes: 74 additions & 0 deletions src/fleet/azext_fleet/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -529,3 +529,77 @@ def delete_fleet_update_strategy(cmd, # pylint: disable=unused-argument
name,
no_wait=False):
return sdk_no_wait(no_wait, client.begin_delete, resource_group_name, fleet_name, name)


def create_auto_upgrade_profile(cmd, # pylint: disable=unused-argument
client,
resource_group_name,
fleet_name,
name,
channel,
update_strategy_id=None,
node_image_selection=None,
disabled=False,
no_wait=False):

if channel == "NodeImage" and node_image_selection is not None:
raise CLIError("node_image_selection must NOT be populated when channel type `NodeImage` is selected")

upgrade_channel_model = cmd.get_models(
"UpgradeChannel",
resource_type=CUSTOM_MGMT_FLEET,
operation_group="auto_upgrade_profiles",
)
upgrade_channel = upgrade_channel_model(channel)

auto_upgrade_node_image_selection = None
if node_image_selection:
auto_upgrade_node_image_selection_model = cmd.get_models(
"AutoUpgradeNodeImageSelection",
resource_type=CUSTOM_MGMT_FLEET,
operation_group="auto_upgrade_profiles",
)
auto_upgrade_node_image_selection = auto_upgrade_node_image_selection_model(type=node_image_selection)

auto_upgrade_profile_model = cmd.get_models(
"AutoUpgradeProfile",
resource_type=CUSTOM_MGMT_FLEET,
operation_group="auto_upgrade_profiles",
)
auto_upgrade_profile = auto_upgrade_profile_model(
update_strategy_id=update_strategy_id,
channel=upgrade_channel,
node_image_selection=auto_upgrade_node_image_selection,
disabled=disabled
)

return sdk_no_wait(no_wait,
client.begin_create_or_update,
resource_group_name,
fleet_name,
name,
auto_upgrade_profile)


def show_auto_upgrade_profile(cmd, # pylint: disable=unused-argument
client,
resource_group_name,
fleet_name,
name):
return client.get(resource_group_name, fleet_name, name)


def list_auto_upgrade_profiles(cmd, # pylint: disable=unused-argument
client,
resource_group_name,
fleet_name):
return client.list_by_fleet(resource_group_name, fleet_name)


def delete_auto_upgrade_profile(cmd, # pylint: disable=unused-argument
client,
resource_group_name,
fleet_name,
name,
no_wait=False):
return sdk_no_wait(no_wait, client.begin_delete, resource_group_name, fleet_name, name)
Loading

0 comments on commit 9f42ff0

Please sign in to comment.