Skip to content
Draft
Show file tree
Hide file tree
Changes from 14 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
102 changes: 102 additions & 0 deletions src/fleet/MANAGED_NAMESPACE_IMPLEMENTATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Fleet Managed Namespace Implementation

This document describes the implementation of the managed namespace functionality for Azure Fleet Manager CLI extension.

## Overview

The implementation adds support for the `az fleet managednamespace` command group with the following commands:

- `create` - Creates or updates a managed namespace
- `delete` - Deletes a fleet managed namespace
- `list` - Lists a fleet's managed namespaces
- `show` - Gets a fleet managed namespace
- `update` - Update a managed namespace

## Implementation Details

### 1. SDK Models Added

**ManagedNamespace** - Main resource model with properties:
- `namespace_name` - The Kubernetes namespace name to create on member clusters
- `labels` - Labels for the managed namespace
- `annotations` - Annotations for the managed namespace
- `provisioning_state` - Status of the last operation
- `status` - Detailed status information

**ManagedNamespaceListResult** - List response model
**ManagedNamespaceStatus** - Status information model
**ManagedNamespaceStatusCondition** - Individual status condition model
**ManagedNamespaceProvisioningState** - Enum for provisioning states

### 2. Operations Added

**ManagedNamespacesOperations** - SDK operations class with methods:
- `list_by_fleet()` - Lists managed namespaces in a fleet
- `get()` - Gets a specific managed namespace
- `begin_create_or_update()` - Creates or updates a managed namespace (LRO)
- `begin_delete()` - Deletes a managed namespace (LRO)

### 3. CLI Commands Added

**Command Group**: `az fleet managednamespace`

**Commands**:
```bash
# Create a managed namespace
az fleet managednamespace create -g MyFleetResourceGroup -f MyFleetName -n my-namespace

# List managed namespaces
az fleet managednamespace list -g MyFleetResourceGroup -f MyFleetName

# Show managed namespace details
az fleet managednamespace show -g MyFleetResourceGroup -f MyFleetName -n my-namespace

# Update managed namespace
az fleet managednamespace update -g MyFleetResourceGroup -f MyFleetName -n my-namespace --labels env=staging

# Delete managed namespace
az fleet managednamespace delete -g MyFleetResourceGroup -f MyFleetName -n my-namespace
```

### 4. Files Modified

1. **vendored_sdks/v2025_04_01_preview/operations/_managed_namespaces_operations.py** - New operations class
2. **vendored_sdks/v2025_04_01_preview/models/_models_py3.py** - Added models
3. **vendored_sdks/v2025_04_01_preview/models/_container_service_fleet_mgmt_client_enums.py** - Added enum
4. **vendored_sdks/v2025_04_01_preview/models/__init__.py** - Updated exports
5. **vendored_sdks/v2025_04_01_preview/operations/__init__.py** - Updated exports
6. **vendored_sdks/v2025_04_01_preview/_container_service_fleet_mgmt_client.py** - Added operations client
7. **_client_factory.py** - Added client factory
8. **commands.py** - Added command group
9. **custom.py** - Added custom command implementations
10. **_params.py** - Added parameter definitions
11. **_help.py** - Added help documentation

### 5. API Endpoints

The implementation assumes the following REST API endpoints:

- `GET /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ContainerService/fleets/{fleetName}/managedNamespaces`
- `GET /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ContainerService/fleets/{fleetName}/managedNamespaces/{managedNamespaceName}`
- `PUT /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ContainerService/fleets/{fleetName}/managedNamespaces/{managedNamespaceName}`
- `DELETE /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ContainerService/fleets/{fleetName}/managedNamespaces/{managedNamespaceName}`

API Version: `2025-04-01-preview`

## Testing

The implementation includes unit tests in `test_fleet_managed_namespace_scenario.py` that verify:

- Creating a managed namespace
- Listing managed namespaces
- Showing managed namespace details
- Updating managed namespace properties
- Deleting a managed namespace

## Notes

- The implementation follows the same patterns as existing fleet subcommands (members, updaterun, etc.)
- All operations support long-running operations (LRO) with `--no-wait` parameter
- The delete operation includes confirmation prompt by default
- Labels and annotations support the same validation as other fleet resources
- The namespace name can be different from the managed namespace resource name
14 changes: 10 additions & 4 deletions src/fleet/azext_fleet/_client_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
ResourceType
)

CUSTOM_MGMT_FLEET = CustomResourceType('azext_fleet.vendored_sdks', 'ContainerServiceFleetMgmtClient')
CUSTOM_MGMT_FLEET = CustomResourceType('azext_fleet.vendored_sdks.v2025_04_01_preview', 'ContainerServiceClient')


# container service clients
def get_container_service_client(cli_ctx, subscription_id=None):
return get_mgmt_service_client(cli_ctx, CUSTOM_MGMT_FLEET, subscription_id=subscription_id)
from .vendored_sdks.v2025_04_01_preview import ContainerServiceClient
return get_mgmt_service_client(cli_ctx, ContainerServiceClient, subscription_id=subscription_id)


def cf_fleets(cli_ctx, *_):
Expand All @@ -25,8 +26,13 @@ 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_managed_namespaces(cli_ctx, *_):
return get_container_service_client(cli_ctx).fleet_managed_namespaces


# Gates functionality - will be available when v2025_04_01_preview API supports gates
# def cf_gates(cli_ctx, *_):
# return get_container_service_client(cli_ctx).gates


def cf_update_runs(cli_ctx, *_):
Expand Down
67 changes: 67 additions & 0 deletions src/fleet/azext_fleet/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,3 +432,70 @@
- name: Approves a gate.
text: az fleet gate approve -g MyFleetResourceGroup --fleet-name MyFleetName --gate-name 3fa85f64-5717-4562-b3fc-2c963f66afa6
"""

helps['fleet managednamespace'] = """
type: group
short-summary: Commands to manage managed namespaces.
"""

helps['fleet managednamespace create'] = """
type: command
short-summary: Creates or updates a managed namespace.
parameters:
- name: --namespace-name
type: string
short-summary: The name of the Kubernetes namespace to be created on member clusters.
- name: --labels
type: string
short-summary: Labels to apply to the managed namespace.
- name: --annotations
type: string
short-summary: Annotations to apply to the managed namespace.
examples:
- name: Create a managed namespace.
text: az fleet managednamespace create -g MyFleetResourceGroup -f MyFleetName -n MyManagedNamespace --namespace-name my-namespace
- name: Create a managed namespace with labels and annotations.
text: az fleet managednamespace create -g MyFleetResourceGroup -f MyFleetName -n MyManagedNamespace --namespace-name my-namespace --labels env=production team=devops --annotations description="Production namespace"
"""

helps['fleet managednamespace update'] = """
type: command
short-summary: Update a managed namespace.
parameters:
- name: --namespace-name
type: string
short-summary: The name of the Kubernetes namespace to be created on member clusters.
- name: --labels
type: string
short-summary: Labels to apply to the managed namespace.
- name: --annotations
type: string
short-summary: Annotations to apply to the managed namespace.
examples:
- name: Update a managed namespace's labels.
text: az fleet managednamespace update -g MyFleetResourceGroup -f MyFleetName -n MyManagedNamespace --labels env=staging
"""

helps['fleet managednamespace list'] = """
type: command
short-summary: Lists a fleet's managed namespaces.
examples:
- name: List all managed namespaces for a given fleet.
text: az fleet managednamespace list -g MyFleetResourceGroup -f MyFleetName
"""

helps['fleet managednamespace show'] = """
type: command
short-summary: Gets a fleet managed namespace.
examples:
- name: Show the details of a specific managed namespace.
text: az fleet managednamespace show -g MyFleetResourceGroup -f MyFleetName -n MyManagedNamespace
"""

helps['fleet managednamespace delete'] = """
type: command
short-summary: Deletes a fleet managed namespace.
examples:
- name: Delete a specific managed namespace.
text: az fleet managednamespace delete -g MyFleetResourceGroup -f MyFleetName -n MyManagedNamespace
"""
23 changes: 23 additions & 0 deletions src/fleet/azext_fleet/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,26 @@ 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('gate_name', options_list=['--gate-name', '--gate', '-n'], help='Name of the gate.')

# Fleet managed namespace arguments
with self.argument_context('fleet managednamespace') 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('managed_namespace_name', options_list=['--name', '-n'], help='Name of the managed namespace.')

with self.argument_context('fleet managednamespace create') as c:
c.argument('labels', labels_type, help='Labels to apply to the managed namespace.')
c.argument('annotations', type=validate_labels, metavar='KEY=VALUE', help='Annotations to apply to the managed namespace: key[=value] [key[=value] ...].')

with self.argument_context('fleet managednamespace update') as c:
c.argument('labels', labels_type, help='Labels to apply to the managed namespace.')
c.argument('annotations', type=validate_labels, metavar='KEY=VALUE', help='Annotations to apply to the managed namespace: key[=value] [key[=value] ...].')

with self.argument_context('fleet managednamespace delete') as c:
pass

with self.argument_context('fleet managednamespace show') as c:
pass

with self.argument_context('fleet managednamespace list') as c:
pass
59 changes: 40 additions & 19 deletions src/fleet/azext_fleet/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,57 +8,67 @@
from azext_fleet._client_factory import (
cf_fleets,
cf_fleet_members,
cf_managed_namespaces,
cf_update_runs,
cf_fleet_update_strategies,
cf_auto_upgrade_profiles,
cf_auto_upgrade_profile_operations,
cf_gates
cf_auto_upgrade_profile_operations
# cf_gates # Will be available when v2025_04_01_preview API supports gates
)


def load_command_table(self, _):

fleets_sdk = CliCommandType(
operations_tmpl="azext_fleet.vendored_sdks.operations._fleets_operations#FleetsOperations.{}",
operations_tmpl="azext_fleet.vendored_sdks.v2025_04_01_preview.operations._operations#FleetsOperations.{}",
operation_group="fleets",
client_factory=cf_fleets
)

fleet_members_sdk = CliCommandType(
operations_tmpl="azext_fleet.vendored_sdks.operations._fleet_members_operations#FleetMembersOperations.{}",
operations_tmpl="azext_fleet.vendored_sdks.v2025_04_01_preview.operations._operations#FleetMembersOperations.{}",
operation_group="fleet_members",
client_factory=cf_fleet_members
)

managed_namespaces_sdk = CliCommandType(
operations_tmpl="azext_fleet.vendored_sdks.v2025_04_01_preview.operations._operations#FleetManagedNamespacesOperations.{}",
operation_group="fleet_managed_namespaces",
client_factory=cf_managed_namespaces
)

update_runs_sdk = CliCommandType(
operations_tmpl="azext_fleet.vendored_sdks.operations._update_runs_operations#UpdateRunsOperations.{}",
operations_tmpl="azext_fleet.vendored_sdks.v2025_04_01_preview.operations._operations#UpdateRunsOperations.{}",
operation_group="update_runs",
client_factory=cf_update_runs
)

fleet_update_strategy_sdk = CliCommandType(
operations_tmpl="azext_fleet.vendored_sdks.operations._fleet_update_strategies_operations#FleetUpdateStrategiesOperations.{}",
operations_tmpl="azext_fleet.vendored_sdks.v2025_04_01_preview.operations._operations#FleetUpdateStrategiesOperations.{}",
operation_group="fleet_update_strategies",
client_factory=cf_fleet_update_strategies
)

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

auto_upgrade_profile_operations_sdk = CliCommandType(
operations_tmpl="azext_fleet.vendored_sdks.operations._auto_upgrade_profile_operations_operations#AutoUpgradeProfileOperationsOperations.{}",
operations_tmpl="azext_fleet.vendored_sdks.v2025_04_01_preview.operations._operations#AutoUpgradeProfileOperationsOperations.{}",
operation_group="auto_upgrade_profile_operations",
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
)
# Gates functionality - will be available when v2025_04_01_preview API supports gates
# gates_sdk = CliCommandType(
# operations_tmpl="azext_fleet.vendored_sdks.v2025_04_01_preview.operations._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:
Expand All @@ -81,6 +91,15 @@ def load_command_table(self, _):
g.custom_command("reconcile", "reconcile_fleet_member", supports_no_wait=True)
g.wait_command("wait")

# fleet managed namespaces command group
with self.command_group("fleet managednamespace", managed_namespaces_sdk, client_factory=cf_managed_namespaces) as g:
g.custom_command("create", "create_managed_namespace", supports_no_wait=True)
g.custom_command("update", "update_managed_namespace", supports_no_wait=True)
g.custom_command("delete", "delete_managed_namespace", supports_no_wait=True, confirmation=True)
g.custom_command("list", "list_managed_namespaces")
g.custom_show_command("show", "show_managed_namespace")
g.wait_command("wait")

# fleet update runs command group
with self.command_group("fleet updaterun", update_runs_sdk, client_factory=cf_update_runs) as g:
g.custom_command("create", "create_update_run", supports_no_wait=True)
Expand Down Expand Up @@ -112,9 +131,11 @@ def load_command_table(self, _):
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_show_command("show", "show_gate")
g.custom_command("update", "update_gate")
g.custom_command("approve", "approve_gate")
# Gates functionality - will be available when v2025_04_01_preview API supports gates
# with self.command_group("fleet gate", gates_sdk, client_factory=cf_gates) as g:
# g.custom_command("list", "list_gates_by_fleet")
# g.custom_show_command("show", "show_gate")
# g.custom_command("update", "update_gate")
# g.custom_command("approve", "approve_gate")


5 changes: 3 additions & 2 deletions src/fleet/azext_fleet/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
UPGRADE_TYPE_NODEIMAGEONLY = "NodeImageOnly"
FLEET_1P_APP_ID = "609d2f62-527f-4451-bfd2-ac2c7850822c"

SUPPORTED_GATE_STATES_FILTERS = ["Pending", "Skipped", "Completed"]
SUPPORTED_GATE_STATES_PATCH = ["Completed"]
# Gates functionality - will be available when v2025_04_01_preview API supports gates
# SUPPORTED_GATE_STATES_FILTERS = ["Pending", "Skipped", "Completed"]
# SUPPORTED_GATE_STATES_PATCH = ["Completed"]

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