Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
18dbf06
20260501-vendored-sdk
JunyuQian Apr 8, 2026
3bb89dd
version update
JunyuQian Apr 8, 2026
46e0a40
WIP support for MCU's MAF field
Apr 13, 2026
26b56c6
feat: add support for updatestrategy memberselector
Apr 14, 2026
a1ebd6d
Allow specifying Rollout Strategy
Apr 13, 2026
38df40b
Add rollout strategy validator test
Apr 13, 2026
7abb1fd
Add rollout strategy to hubful namespace scenario
Apr 14, 2026
b228e11
Use rollout strategy type constants
Apr 14, 2026
26e97fb
Validate parameter instead of derived object
Apr 14, 2026
2159dec
Add namespace update command
Apr 15, 2026
d59cd0a
Add help text
Apr 15, 2026
ccf7802
Extract polling interval into a constant
Apr 15, 2026
f110dab
add scheduled start gate
JunyuQian Apr 8, 2026
7968906
filter by gate type
JunyuQian Apr 8, 2026
fa284ae
enhance code style
JunyuQian Apr 8, 2026
29fb460
bug fixes
JunyuQian Apr 13, 2026
c572c10
Regenerate 0501preview vendored sdks
May 7, 2026
2a85d84
fix test for memberselector
May 8, 2026
8508c04
fix keyerror for empty groups
May 13, 2026
156951c
bugbash error fixes
JunyuQian May 15, 2026
8a7ce3a
include gateType filter in the gate list scenario
JunyuQian May 15, 2026
985a82b
revert helper change
JunyuQian May 15, 2026
c86ba67
rebase error fix
JunyuQian May 19, 2026
03a497e
regenerate sdk after rebase 0302
JunyuQian May 19, 2026
7c46fda
generate test recordings
JunyuQian May 19, 2026
84e3606
Infer rollout strategy from cluster update strategy
May 20, 2026
a4a3ed2
Mark cluster update strategy as preview
May 20, 2026
5554c3e
Remove rollout strategy references
May 20, 2026
a99e804
Rename cluster-update-strategy to rollout-update-strategy
May 20, 2026
39b1047
Default to RollingUpdate on create but not defaulting to anything on …
May 20, 2026
4d8dfc3
Regenerate hubful test recording
May 20, 2026
a43c543
add scheduled start gate tests
JunyuQian May 29, 2026
26a6ea5
re-generate fleet-hubless recording
JunyuQian May 29, 2026
c97fc6d
Merge pull request #17 from JunyuQian/add-scheduled-start-tests
JunyuQian May 29, 2026
804b43f
Fix examples
May 29, 2026
b5c0cc2
Merge pull request #16 from JunyuQian/weiweng/fleet-0501preview-cli-u…
weng271190436 May 29, 2026
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 @@ -184,4 +184,8 @@ Release History

1.10.1
++++++
* Add SDK generation script for regenerating vendored SDK from azure-rest-api-specs.
* Add SDK generation script for regenerating vendored SDK from azure-rest-api-specs.

2.1.0
++++++
* Add 2026-05-01-preview API version with vendored generated SDK.
50 changes: 44 additions & 6 deletions src/fleet/azext_fleet/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,23 +207,31 @@
az fleet updaterun create -g MyResourceGroup -f MyFleet -n MyUpdateRun --upgrade-type Full --kubernetes-version 1.25.0 --node-image-selection Latest --stages ./test/stages.json

The following JSON structure represents example contents of the parameter '--stages ./test/stages.json'.
A stages array is composed of one or more stages, each containing one or more groups.
A stages array is composed of one or more stages, each containing one or more groups and/or a memberSelector.
Each group contains the 'name' property, which represents the group to which a cluster belongs (see 'az fleet member create --help').
Stages and groups can optionally include a 'memberSelector' to filter members by label. A 'memberSelector' contains a 'byLabel' property with a Kubernetes-style label selector string (e.g., "env=production"). When set on a group, it overrides name-based matching.
Stage memberSelector: pre-filters members for the entire stage. Only matching members are candidates for group-level matching.
Group memberSelector: selects members by label instead of matching by FleetMember.Group name. When set, overrides name-based matching.
Stages have an optional 'afterStageWaitInSeconds' integer property, acting as a delay between stage execution.
Stages and groups have an optional 'maxConcurrency' string property that sets the maximum number of concurrent upgrades allowed. It acts as a ceiling (not a quota)—actual concurrency may be lower due to other limits or member conditions. Minimum is 1.
Stage maxConcurrency: applies across all groups in the stage (total concurrent upgrades for the whole stage).
Group maxConcurrency: applies within a single group, and is additionally constrained by the stage limit (effective max is min(group cluster count, stage maxConcurrency)). Minimum is 1.
Stages and groups also have an optional 'maxAllowedFailures' string property.
Stage maxAllowedFailures: The maximum number of member (cluster) upgrade failures tolerated in this stage. Accepts a non-negative integer (e.g. '3') or a percentage (e.g. '25%'). Defaults to 0 if unset, meaning any failure fails the stage.
Group maxAllowedFailures: The maximum number of member (cluster) upgrade failures tolerated in this group. Accepts a non-negative integer (e.g. '3') or a percentage (e.g. '25%'). Defaults to 0 if unset, meaning any failure fails the group.
Value formats:
Fixed count (e.g., 3)
Percentage (e.g., 25%, 1–100) of the relevant cluster total (stage total for stage, group total for group). Percentages are rounded down, with a minimum of 1 enforced.
Examples: 3, 25%, 100%
Percentage (e.g., 25%, 1–100) of the relevant cluster total (stage total for stage, group total for group).
Examples: 0, 3, 25%, 100%

Example stages JSON, with optional properties maxConcurrency and before/after gates:
Example stages JSON, with optional properties maxConcurrency, maxAllowedFailures and before/after gates:
{
"stages": [
{
"name": "stage1",
"memberSelector": { "byLabel": "env=staging" },
"maxConcurrency": "7%",
"maxAllowedFailures": "50%",
"beforeGates": [
{
"displayName": "stage before gate",
Expand All @@ -239,7 +247,9 @@
"groups": [
{
"name": "group-a1",
"memberSelector": { "byLabel": "tier=frontend" },
"maxConcurrency": "100%",
"maxAllowedFailures": "5",
"beforeGates": [
{
"displayName": "group before gate",
Expand All @@ -255,7 +265,9 @@
},
{
"name": "group-a2",
"memberSelector": { "byLabel": "tier=backend" },
"maxConcurrency": "1",
"maxAllowedFailures": "25%",
"beforeGates": [
{
"displayName": "group before gate",
Expand Down Expand Up @@ -290,6 +302,18 @@
},
{
"name": "stage2",
"memberSelector": { "byLabel": "env=production" },
"beforeGates": [
{
"displayName": "Wait until Friday evening",
"type": "ScheduledStart",
"scheduledStartConfiguration": {
"startDay": "Friday",
"startTime": "18:00",
"utcOffset": "-05:00"
}
}
],
"groups": [
{
"name": "group-b1"
Expand Down Expand Up @@ -477,6 +501,10 @@
text: az fleet gate list -g MyFleetResourceGroup --fleet-name MyFleetName
- name: List all gates, filtering on gate state. Valid values are ('Pending', 'Skipped', 'Completed').
text: az fleet gate list -g MyFleetResourceGroup --fleet-name MyFleetName --state Pending
- name: List all gates, filtering on gate type. Valid values are ('Approval', 'ScheduledStart').
text: az fleet gate list -g MyFleetResourceGroup --fleet-name MyFleetName --gate-type ScheduledStart
- name: List pending ScheduledStart gates.
text: az fleet gate list -g MyFleetResourceGroup --fleet-name MyFleetName --gate-type ScheduledStart --state Pending
"""

helps['fleet gate show'] = """
Expand Down Expand Up @@ -520,16 +548,26 @@
text: az fleet namespace create -g MyFleetResourceGroup -f MyFleetName -n MyManagedNamespace --annotations key=value --labels key=value --cpu-requests 1m --cpu-limits 4m --memory-requests 1Mi --memory-limits 4Mi --ingress-policy AllowAll --egress-policy DenyAll --delete-policy Keep --adoption-policy Never
- name: Create a fleet managed namespace on specific member clusters.
text: az fleet namespace create -g MyFleetResourceGroup -f MyFleetName -n MyManagedNamespace --member-cluster-names team-01 team-02 team-03 team-04
- name: Create a fleet managed namespace with a rollout update strategy.
text: az fleet namespace create -g MyFleetResourceGroup -f MyFleetName -n MyManagedNamespace --member-cluster-names team-01 team-02 --rollout-update-strategy MyUpdateStrategy
"""

helps['fleet namespace update'] = """
type: command
short-summary: Updates a fleet managed namespace.
examples:
- name: Updates a fleet managed namespace.
text: az fleet namespace update -g MyFleetResourceGroup -f MyFleetName -n MyManagedNamespace
- name: Update tags for a fleet managed namespace.
text: az fleet namespace update -g MyFleetResourceGroup -f MyFleetName -n MyManagedNamespace --tags environment=production
- name: Update labels and annotations.
text: az fleet namespace update -g MyFleetResourceGroup -f MyFleetName -n MyManagedNamespace --labels env=production team=devops --annotations owner=team-a
- name: Update resource quotas.
text: az fleet namespace update -g MyFleetResourceGroup -f MyFleetName -n MyManagedNamespace --cpu-requests 1m --cpu-limits 4m --memory-requests 1Mi --memory-limits 4Mi
- name: Update network and lifecycle policies.
text: az fleet namespace update -g MyFleetResourceGroup -f MyFleetName -n MyManagedNamespace --ingress-policy AllowAll --egress-policy DenyAll --adoption-policy IfIdentical --delete-policy Delete
- name: Update member cluster placement.
text: az fleet namespace update -g MyFleetResourceGroup -f MyFleetName -n MyManagedNamespace --member-cluster-names team-01 team-02 team-03
- name: Update with a rollout update strategy.
text: az fleet namespace update -g MyFleetResourceGroup -f MyFleetName -n MyManagedNamespace --rollout-update-strategy my-update-strategy
"""

helps['fleet namespace list'] = """
Expand Down
16 changes: 15 additions & 1 deletion src/fleet/azext_fleet/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
validate_targets,
validate_update_strategy_id,
validate_labels,
validate_enable_vnet_integration
validate_enable_vnet_integration,
)

labels_type = CLIArgumentType(
Expand Down Expand Up @@ -160,6 +160,7 @@ 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('state_filter', options_list=['--state-filter', '--state'], help='Apply a filter on gate state. Valid values are: Pending, Skipped, Completed')
c.argument('gate_type', options_list=['--gate-type'], help='Apply a filter on gate type. Valid values are: Approval, ScheduledStart')

with self.argument_context('fleet gate show') as c:
c.argument('resource_group_name', options_list=['--resource-group', '-g'], help='Name of the resource group.')
Expand Down Expand Up @@ -200,9 +201,22 @@ def load_arguments(self, _):
c.argument('delete_policy', help='Delete policy for the namespace.', arg_type=get_enum_type(['Keep', 'Delete']), default='Keep')
c.argument('adoption_policy', help='Adoption policy for the namespace.', arg_type=get_enum_type(['Always', 'IfIdentical', 'Never']), default='Never')
c.argument('member_cluster_names', nargs='*', validator=validate_member_cluster_names, help='Space-separated list of member cluster names to apply the namespace to.')
c.argument('rollout_update_strategy', help='Name of an existing cluster staged update strategy. When specified, rollout strategy is automatically set to External; otherwise defaults to RollingUpdate.', is_preview=True)

with self.argument_context('fleet namespace update') as c:
c.argument('tags', tags_type)
c.argument('labels', labels_type, help='Space-separated labels in key=value format. Example: env=production region=us-west team=devops')
c.argument('annotations', labels_type, help='Space-separated annotations in key=value format. Example: env=production region=us-west team=devops')
c.argument('cpu_requests', help='CPU requests for the namespace. Example: 1000m')
c.argument('cpu_limits', help='CPU limits for the namespace. Example: 1000m')
c.argument('memory_requests', help='Memory requests for the namespace. Example: 500Mi')
c.argument('memory_limits', help='Memory limits for the namespace. Example: 500Mi')
c.argument('ingress_policy', help='Ingress policy for the namespace', arg_type=get_enum_type(['DenyAll', 'AllowAll', 'AllowSameNamespace']))
c.argument('egress_policy', help='Egress policy for the namespace', arg_type=get_enum_type(['DenyAll', 'AllowAll', 'AllowSameNamespace']))
c.argument('delete_policy', help='Delete policy for the namespace.', arg_type=get_enum_type(['Keep', 'Delete']))
c.argument('adoption_policy', help='Adoption policy for the namespace.', arg_type=get_enum_type(['Always', 'IfIdentical', 'Never']))
c.argument('member_cluster_names', nargs='*', validator=validate_member_cluster_names, help='Space-separated list of member cluster names to apply the namespace to.')
c.argument('rollout_update_strategy', help='Name of the cluster update strategy. When specified, rollout strategy is automatically set to External; otherwise defaults to RollingUpdate.', is_preview=True)

with self.argument_context('fleet namespace get-credentials') as c:
c.argument('managed_namespace_name', options_list=['--name', '-n'], help='Specify the managed namespace name.')
Expand Down
2 changes: 1 addition & 1 deletion src/fleet/azext_fleet/azext_metadata.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"azext.isPreview": false,
"azext.minCliCoreVersion": "2.61.0",
"version": "1.10.1"
"version": "2.1.0"
}
3 changes: 3 additions & 0 deletions src/fleet/azext_fleet/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@
NETWORK_CONTRIBUTOR_ROLE_ID = "4d97b98b-1d4f-4787-a291-c67834d212e7"

SUPPORTED_GATE_STATES_FILTERS = ["Pending", "Skipped", "Completed"]
SUPPORTED_GATE_TYPE_FILTERS = ["Approval", "ScheduledStart"]
SUPPORTED_GATE_STATES_PATCH = ["Completed"]

POLLING_INTERVAL_SECS = 5

UPGRADE_TYPE_ERROR_MESSAGES = {
UPGRADE_TYPE_CONTROLPLANEONLY: f"Please set kubernetes version when upgrade type is '{UPGRADE_TYPE_CONTROLPLANEONLY}'.", # pylint: disable=line-too-long
UPGRADE_TYPE_FULL: f"Please set kubernetes version when upgrade type is '{UPGRADE_TYPE_FULL}'.",
Expand Down
Loading
Loading