Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
9 changes: 8 additions & 1 deletion src/fleet/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,11 @@ Release History

1.5.2
++++++
* Bug fix for `az fleet create --enable-hub --enable-private-cluster` argument
* Bug fix for `az fleet create --enable-hub --enable-private-cluster` argument

1.6.0
++++++
* Upgrade SDK version to 2025-04-01-preview
* Add Fleet Gates support
* Add TargetKubernetesVersion channel support
* Add Fleet Member labels support
2 changes: 1 addition & 1 deletion src/fleet/azext_fleet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def register_fleet_resource_type():
register_resource_type(
"latest",
CUSTOM_MGMT_FLEET,
SDKProfile("2025-03-01"),
SDKProfile("2025-04-01-preview"),
)


Expand Down
2 changes: 2 additions & 0 deletions src/fleet/azext_fleet/_client_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ def cf_fleets(cli_ctx, *_):
def cf_fleet_members(cli_ctx, *_):
return get_container_service_client(cli_ctx).fleet_members

def cf_gates(cli_ctx, *_):
return get_container_service_client(cli_ctx).gates

def cf_update_runs(cli_ctx, *_):
return get_container_service_client(cli_ctx).update_runs
Expand Down
33 changes: 32 additions & 1 deletion src/fleet/azext_fleet/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
short-summary: Update group of the member.
examples:
- name: Create a member and assign it to an update group.
text: az fleet member create -g MyFleetResourceGroup -f MyFleetName -n NameOfMember --update-group UpdateGroup1 --member-cluster-id "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MyFleetResourceGroup/providers/Microsoft.ContainerService/managedClusters/MyManagedCluster"
text: az fleet member create -g MyFleetResourceGroup -f MyFleetName -n NameOfMember --update-group group1 --member-cluster-id "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MyFleetResourceGroup/providers/Microsoft.ContainerService/managedClusters/MyManagedCluster"
"""

helps['fleet member update'] = """
Expand Down Expand Up @@ -393,3 +393,34 @@
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.
"""

helps['fleet gate'] = """
Comment thread
frantran marked this conversation as resolved.
type: group
short-summary: Commands to manage gates.
"""

helps['fleet gate list'] = """
type: command
short-summary: Lists all gates under a fleet.
examples:
- name: Lists all gates under a fleet.
text: az fleet list -g MyFleetResourceGroup --fleet-name MyFleetName
Comment thread
frantran marked this conversation as resolved.
Outdated
- name: List all gates with filtering.
text: az fleet gate list -g MyFleetResourceGroup --fleet-name MyFleetName --query "[?state=='Pending']" -o table
Comment thread
frantran marked this conversation as resolved.
Outdated
"""

helps['fleet gate get'] = """
Comment thread
frantran marked this conversation as resolved.
Outdated
type: command
short-summary: Gets a specific gate.
examples:
- name: Gets a specific gate.
text: az fleet get -g MyFleetResourceGroup --fleet-name MyFleetName --gate-name MyGate
"""

helps['fleet gate update'] = """
type: command
short-summary: Updates a gate. Currently only the gate state can be updated.
examples:
- name: Updates a gate.
text: az fleet gate update -g MyFleetResourceGroup --fleet-name MyFleetName --gate-name MyGate --state "Completed"
"""
57 changes: 53 additions & 4 deletions src/fleet/azext_fleet/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
file_type,
get_location_type,
get_enum_type,
get_three_state_flag
get_three_state_flag,
CLIArgumentType
)
from azure.cli.core.commands.validators import get_default_location_from_resource_group
from azext_fleet._validators import (
Expand All @@ -23,8 +24,14 @@
validate_vm_size,
validate_targets,
validate_update_strategy_id,
validate_labels
)

labels_type = CLIArgumentType(
metavar='KEY=VALUE',
type=validate_labels,
help='Space-separated labels: key[=value] [key[=value] ...]. Example: env=production region=us-west team=devops'
)

def load_arguments(self, _):
with self.argument_context('fleet') as c:
Expand Down Expand Up @@ -62,9 +69,23 @@ def load_arguments(self, _):
with self.argument_context('fleet member create') as c:
c.argument('member_cluster_id', validator=validate_member_cluster_id)
c.argument('update_group')
c.argument(
'member_labels',
labels_type,
options_list=['--member-labels', '--labels'],
help='Space-separated labels in key=value format. Example: env=production region=us-west team=devops'
)


with self.argument_context('fleet member update') as c:
c.argument('update_group')
c.argument(
'member_labels',
labels_type,
options_list=['--member-labels', '--labels'],
help='Space-separated labels in key=value format. Example: env=production region=us-west team=devops'
)


with self.argument_context('fleet updaterun') as c:
c.argument('name', options_list=['--name', '-n'], help='Specify name for the update run.')
Expand Down Expand Up @@ -100,12 +121,22 @@ def load_arguments(self, _):
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']),
c.argument('channel', options_list=['--channel', '-c'], arg_type=get_enum_type(['Stable', 'Rapid', 'NodeImage', 'TargetKubernetesVersion']),
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')
help='Node Image Selection is an option that lets you choose how your clusters\' nodes are upgraded.')
c.argument('target_kubernetes_version',
help=(
'This is the target Kubernetes version for auto-upgrade. The format must be "{major version}.{minor version}". '
'For example, "1.30". By default, this is empty. '
'If the upgrade channel is set to TargetKubernetesVersion, this field must not be empty. '
'If the upgrade channel is Rapid, Stable, or NodeImage, this field must be empty.'
)
)
c.argument('disabled', action='store_true',
help='The disabled flag ensures auto upgrade profile does not run by default')
help='The disabled flag ensures auto upgrade profile does not run by default.')
c.argument('long_term_support', action='store_true', options_list=['--long-term-support', '--lts'],
help='If upgrade channel is not TargetKubernetesVersion, this field must be False. If set to True: Fleet auto upgrade will generate update runs for patches of minor versions earlier than N-2 (where N is the latest supported minor version) if those minor versions support Long-Term Support (LTS). By default, this is set to False.')

with self.argument_context('fleet autoupgradeprofile wait') as c:
c.argument('auto_upgrade_profile_name', options_list=['--auto-upgrade-profile-name', '--profile-name'],
Expand All @@ -115,3 +146,21 @@ def load_arguments(self, _):
c.argument('resource_group_name', options_list=['--resource-group', '-g'], help='Name of the resource group.')
c.argument('fleet_name', options_list=['--fleet-name', '-f'], help='Name of the fleet.')
c.argument('auto_upgrade_profile_name', options_list=['--auto-upgrade-profile-name', '--profile-name', '--name', '-n'], help='Name of the auto upgrade profile.')


with self.argument_context('fleet gate list') as c:
c.argument('resource_group_name', options_list=['--resource-group', '-g'], help='Name of the resource group.')
c.argument('fleet_name', options_list=['--fleet-name', '-f'], help='Name of the fleet.')
Comment thread
frantran marked this conversation as resolved.

with self.argument_context('fleet gate get') as c:
c.argument('resource_group_name', options_list=['--resource-group', '-g'], help='Name of the resource group.')
c.argument('fleet_name', options_list=['--fleet-name', '-f'], help='Name of the fleet.')
c.argument('gate_name', options_list=['--gate-name', '-n'], help='Name of the gate.')

with self.argument_context('fleet gate update') as c:
c.argument('resource_group_name', options_list=['--resource-group', '-g'], help='Name of the resource group.')
c.argument('fleet_name', options_list=['--fleet-name', '-f'], help='Name of the fleet.')
c.argument('gate_name', options_list=['--gate-name', '-n'], help='Name of the gate.')
c.argument('gate_state',options_list=['--gate-state', '--gs', '--state'],
help='The Gate State to patch. Valid values are Pending, Skipped, Completed.')

9 changes: 9 additions & 0 deletions src/fleet/azext_fleet/_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,12 @@ def validate_update_strategy_id(namespace):
if not is_valid_resource_id(update_strategy_id):
raise InvalidArgumentValueError(
"--update-strategy-id is not a valid Azure resource ID.")

def validate_labels(val):
result = {}
for item in val.split():
if '=' not in item:
raise ValueError("Expected key=value format")
k, v = item.split('=', 1)
result[k] = v
return result
16 changes: 14 additions & 2 deletions src/fleet/azext_fleet/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
cf_update_runs,
cf_fleet_update_strategies,
cf_auto_upgrade_profiles,
cf_auto_upgrade_profile_operations

cf_auto_upgrade_profile_operations,
cf_gates
)


Expand Down Expand Up @@ -54,6 +54,12 @@ def load_command_table(self, _):
client_factory=cf_auto_upgrade_profile_operations
)

gates_sdk = CliCommandType(
operations_tmpl="azext_fleet.vendored_sdks.operations._gates_operations#GatesOperations.{}",
operation_group="gates",
client_factory=cf_gates
)

# 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 @@ -105,3 +111,9 @@ def load_command_table(self, _):
# auto upgrade profiles operation command group
with self.command_group("fleet autoupgradeprofile", auto_upgrade_profile_operations_sdk, client_factory=cf_auto_upgrade_profile_operations) as g:
g.custom_command("generate-update-run", "generate_update_run", supports_no_wait=True)

# fleet gates command group
with self.command_group("fleet gate", gates_sdk, client_factory=cf_gates) as g:
g.custom_command("list", "list_gates_by_fleet")
g.custom_command("get", "get_gate")
g.custom_command("update", "update_gate")
38 changes: 36 additions & 2 deletions src/fleet/azext_fleet/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,13 +236,14 @@ def create_fleet_member(cmd,
fleet_name,
member_cluster_id,
update_group=None,
member_labels=None,
no_wait=False):
fleet_member_model = cmd.get_models(
"FleetMember",
resource_type=CUSTOM_MGMT_FLEET,
operation_group="fleet_members"
)
fleet_member = fleet_member_model(cluster_resource_id=member_cluster_id, group=update_group)
fleet_member = fleet_member_model(cluster_resource_id=member_cluster_id, group=update_group, labels=member_labels)
return sdk_no_wait(no_wait, client.begin_create, resource_group_name, fleet_name, name, fleet_member)


Expand All @@ -252,13 +253,14 @@ def update_fleet_member(cmd,
name,
fleet_name,
update_group=None,
member_labels=None,
no_wait=False):
fleet_member_update_model = cmd.get_models(
"FleetMemberUpdate",
resource_type=CUSTOM_MGMT_FLEET,
operation_group="fleet_members"
)
properties = fleet_member_update_model(group=update_group)
properties = fleet_member_update_model(group=update_group, labels=member_labels)
return sdk_no_wait(no_wait, client.begin_update, resource_group_name, fleet_name, name, properties)


Expand Down Expand Up @@ -543,6 +545,8 @@ def create_auto_upgrade_profile(cmd, # pylint: disable=unused-argument
channel,
update_strategy_id=None,
node_image_selection=None,
target_kubernetes_version=None,
long_term_support=False,
disabled=False,
no_wait=False):

Expand Down Expand Up @@ -574,6 +578,8 @@ def create_auto_upgrade_profile(cmd, # pylint: disable=unused-argument
update_strategy_id=update_strategy_id,
channel=upgrade_channel,
node_image_selection=auto_upgrade_node_image_selection,
target_kubernetes_version=target_kubernetes_version,
long_term_support=long_term_support,
disabled=disabled
)

Expand Down Expand Up @@ -622,3 +628,31 @@ def generate_update_run(cmd, # pylint: disable=unused-argument
fleet_name,
auto_upgrade_profile_name
)

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

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

def update_gate(cmd, # pylint: disable=unused-argument
client,
resource_group_name,
fleet_name,
gate_name,
gate_state=None):

gate_model = cmd.get_models(
"GatePatch",
resource_type=CUSTOM_MGMT_FLEET,
operation_group="gates"
)
properties = gate_models(gate_state=gate_state)
return sdk_no_wait(no_wait, client.begin_update, resource_group_name, fleet_name, gate_name, properties)
Loading
Loading