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

[fleet] add fleet auto upgrade profile commands #7887

Merged
merged 12 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
6 changes: 5 additions & 1 deletion src/fleet/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,8 @@ Release History

1.2.1
++++++
* Fixed --vm-size parameter mapping
* Fixed --vm-size parameter mapping

1.2.2
++++++
* 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 -l MyLocation -f MyFleetName -n MyAutoUpgradeProfileName -c Rapid --disabled
pdaru marked this conversation as resolved.
Show resolved Hide resolved
- name: Create an auto upgrade profile with channel 'NodeImage'.
text: az fleet autoupgradeprofile create -g MyFleetResourceGroup -l MyLocation -f MyFleetName -n MyAutoUpgradeProfileName -c NodeImage --node-image-selection-type Latest
pdaru marked this conversation as resolved.
Show resolved Hide resolved
"""

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 -l MyLocation -f MyFleetName -n MyAutoUpgradeProfileName
pdaru marked this conversation as resolved.
Show resolved Hide resolved
"""

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 -l MyLocation -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 autouprgadeprofile list -g MyFleetResourceGroup -l MyLocation -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.
"""
70 changes: 54 additions & 16 deletions src/fleet/azext_fleet/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,35 +13,53 @@
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)

with self.argument_context('fleet create') as c:
c.argument('tags', tags_type)
c.argument('dns_name_prefix', options_list=['--dns-name-prefix', '-p'])
c.argument('enable_private_cluster', action='store_true', help='Whether to create the Fleet hub as a private cluster or not.')
c.argument('enable_vnet_integration', action='store_true', is_preview=True, help='Whether to enable apiserver vnet integration for the Fleet hub or not.')
c.argument('apiserver_subnet_id', validator=validate_apiserver_subnet_id, is_preview=True, help='The subnet to be used when apiserver vnet integration is enabled.')
c.argument('agent_subnet_id', validator=validate_agent_subnet_id, help='The ID of the subnet which the Fleet hub node will join on startup.')
c.argument('enable_managed_identity', action='store_true', 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 by specifying the user assigned identity\'s resource Id.')
c.argument('enable_private_cluster', action='store_true',
help='Whether to create the Fleet hub as a private cluster or not.')
c.argument('enable_vnet_integration', action='store_true', is_preview=True,
help='Whether to enable apiserver vnet integration for the Fleet hub or not.')
c.argument('apiserver_subnet_id', validator=validate_apiserver_subnet_id, is_preview=True,
help='The subnet to be used when apiserver vnet integration is enabled.')
c.argument('agent_subnet_id', validator=validate_agent_subnet_id,
help='The ID of the subnet which the Fleet hub node will join on startup.')
c.argument('enable_managed_identity', action='store_true',
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 by specifying the user assigned identity\'s resource Id.')
c.argument('enable_hub', action='store_true', help='If set, the Fleet will be created with a hub cluster.')
c.argument('vm_size', validator=validate_vm_size, help='The virtual machine size of the Fleet hub.')

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 +79,36 @@ 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_type', 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')
11 changes: 11 additions & 0 deletions src/fleet/azext_fleet/_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,14 @@ 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'.")


# https://github.com/Azure/azure-cli/blob/master/doc/authoring_command_modules/authoring_commands.md#supporting-name-or-id-parameters
def validate_update_strategy_id(namespace):
update_strategy_id = namespace.update_strategy_id
if update_strategy_id is None:
return
from msrestazure.tools import is_valid_resource_id
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_type=None,
disabled=False,
no_wait=False):

if channel == "NodeImage" and node_image_selection_type is not None:
raise CLIError("node_image_selection_type 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_type:
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_type)

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
Loading