Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions src/k8s-extension/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
Release History
===============

1.2.6
++++++++++++++++++
* k8s-extension new sub command group for extension types

1.2.5
++++++++++++++++++
* microsoft.azuremonitor.containers: ContainerInsights Extension Managed Identity Auth Onboarding related bug fixes.
Expand Down
33 changes: 33 additions & 0 deletions src/k8s-extension/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Microsoft Azure CLI 'k8s-extension' Extension
This package is for the 'k8s-extension' extension.
i.e. 'az k8s-extension'

This package includes the 'extension-types' subgroup.
i.e. 'az k8s-extension extension-types'

### How to use ###
Install this extension using the below CLI command
```
Expand Down Expand Up @@ -71,3 +74,33 @@ az k8s-extension update \
--configuration-settings-file configSettingsFile \
--configuration-protected-settings-file protectedSettingsFile
```

##### List available extension types of a cluster
```
az k8s-extension extension-types list \
--resource-group groupName \
--cluster-name clusterName \
--cluster-type clusterType
```

##### List available extension types by location
```
az k8s-extension extension-types list-by-location \
--location location
```

##### Show an extension types of a cluster
```
az k8s-extension extension-types show \
--resource-group groupName \
--cluster-name clusterName \
--cluster-type clusterType \
--name extensionName
```

##### List all versions of an extension type by release train
```
az k8s-extension extension-types list-versions \
--location location \
--name extensionName
```
21 changes: 19 additions & 2 deletions src/k8s-extension/azext_k8s_extension/_client_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,34 @@

from azure.cli.core.commands.client_factory import get_mgmt_service_client
from azure.cli.core.profiles import ResourceType
from . import consts


def cf_k8s_extension(cli_ctx, *_):
def cf_k8s_extension(cli_ctx, **kwargs):
from .vendored_sdks import SourceControlConfigurationClient
return get_mgmt_service_client(cli_ctx, SourceControlConfigurationClient)
return get_mgmt_service_client(cli_ctx, SourceControlConfigurationClient, **kwargs)


def cf_k8s_extension_operation(cli_ctx, _):
return cf_k8s_extension(cli_ctx).extensions


def cf_k8s_cluster_extension_types_operation(cli_ctx, _):
return cf_k8s_extension(cli_ctx, consts.EXTENSION_TYPE_API_VERSION).cluster_extension_types


def cf_k8s_cluster_extension_type_operation(cli_ctx, _):
return cf_k8s_extension(cli_ctx, consts.EXTENSION_TYPE_API_VERSION).cluster_extension_type


def cf_k8s_location_extension_types_operation(cli_ctx, _):
return cf_k8s_extension(cli_ctx, consts.EXTENSION_TYPE_API_VERSION).location_extension_types


def cf_k8s_extension_type_versions_operation(cli_ctx, _):
return cf_k8s_extension(cli_ctx, consts.EXTENSION_TYPE_API_VERSION).extension_type_versions


def cf_resource_groups(cli_ctx, subscription_id=None):
return get_mgmt_service_client(cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES,
subscription_id=subscription_id).resource_groups
Expand Down
45 changes: 45 additions & 0 deletions src/k8s-extension/azext_k8s_extension/_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,48 @@ def __get_table_row(result):
('provisioningState', result.get('provisioningState', '')),
('lastModifiedAt', result.get('systemData', {}).get('lastModifiedAt', '')),
])


def k8s_extension_types_list_table_format(results):
return [__get_extension_type_table_row(result, False) for result in results]


def k8s_extension_type_show_table_format(result):
return __get_extension_type_table_row(result, True)


def __get_extension_type_table_row(result, showReleaseTrains):
# Populate the values to be returned if they are not undefined
clusterTypes = ', '.join(result['clusterTypes'])
name = result['name']
defaultScope, allowMultipleInstances, defaultReleaseNamespace = '', '', ''
if result['supportedScopes']:
defaultScope = result['supportedScopes']['defaultScope']
if result['supportedScopes']['clusterScopeSettings']:
allowMultipleInstances = result['supportedScopes']['clusterScopeSettings']['allowMultipleInstances']
defaultReleaseNamespace = result['supportedScopes']['clusterScopeSettings']['defaultReleaseNamespace']

retVal = OrderedDict([
('name', name),
('defaultScope', defaultScope),
('clusterTypes', clusterTypes),
('allowMultipleInstances', allowMultipleInstances),
('defaultReleaseNamespace', defaultReleaseNamespace)
])
if showReleaseTrains:
releaseTrains = ', '.join(result['releaseTrains'])
retVal['releaseTrains'] = releaseTrains

return retVal


def k8s_extension_type_versions_list_table_format(results):
return [__get_extension_type_versions_table_row(result) for result in results]


def __get_extension_type_versions_table_row(result):
versions = ", ".join(result['versions'])
return OrderedDict([
('releaseTrain', result['releaseTrain']),
('versions', versions)
])
44 changes: 44 additions & 0 deletions src/k8s-extension/azext_k8s_extension/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,47 @@
--configuration-settings-file=config-settings-file \
--configuration-protected-settings-file=protected-settings-file
"""

helps[f'{consts.EXTENSION_NAME} extension-types'] = """
type: group
short-summary: Commands to discover Kubernetes Extension Types.
"""

helps[f'{consts.EXTENSION_NAME} extension-types list'] = f"""
type: command
short-summary: List Kubernetes Extension Types.
examples:
- name: List Kubernetes Extension Types
text: |-
az {consts.EXTENSION_NAME} extension-types list --resource-group my-resource-group \
--cluster-name mycluster --cluster-type connectedClusters
"""

helps[f'{consts.EXTENSION_NAME} extension-types list-by-location'] = f"""
type: command
short-summary: List available Kubernetes Extension Types in a specified region.
examples:
- name: List Kubernetes Extension Types by location
text: |-
az {consts.EXTENSION_NAME} extension-types list-by-location --location eastus2euap
"""

helps[f'{consts.EXTENSION_NAME} extension-types show'] = f"""
type: command
short-summary: Show properties for a Kubernetes Extension Type.
examples:
- name: Show Kubernetes Extension Type
text: |-
az {consts.EXTENSION_NAME} extension-types show --resource-group my-resource-group \
--cluster-name mycluster --cluster-type connectedClusters --extension-type cassandradatacenteroperator
"""

helps[f'{consts.EXTENSION_NAME} extension-types list-versions'] = f"""
type: command
short-summary: List available versions for a Kubernetes Extension Type.
examples:
- name: List versions for an Extension Type
text: |-
az {consts.EXTENSION_NAME} extension-types list-versions --location eastus2euap \
--extension-type cassandradatacenteroperator
"""
30 changes: 30 additions & 0 deletions src/k8s-extension/azext_k8s_extension/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,33 @@ def load_arguments(self, _):
help='Ignore confirmation prompts')
c.argument('force',
help='Specify whether to force delete the extension from the cluster.')

with self.argument_context(f"{consts.EXTENSION_NAME} extension-types list") as c:
c.argument('cluster_name',
options_list=['--cluster-name', '-c'],
help='Name of the Kubernetes cluster')
c.argument('cluster_type',
arg_type=get_enum_type(['connectedClusters', 'managedClusters', 'appliances']),
options_list=['--cluster-type', '-t'],
help='Specify Arc clusters or AKS managed clusters or Arc appliances.')

with self.argument_context(f"{consts.EXTENSION_NAME} extension-types list-by-location") as c:
c.argument('location',
validator=get_default_location_from_resource_group)

with self.argument_context(f"{consts.EXTENSION_NAME} extension-types show") as c:
c.argument('extension_type',
help='Name of the extension type.')
c.argument('cluster_name',
options_list=['--cluster-name', '-c'],
help='Name of the Kubernetes cluster')
c.argument('cluster_type',
arg_type=get_enum_type(['connectedClusters', 'managedClusters', 'appliances']),
options_list=['--cluster-type', '-t'],
help='Specify Arc clusters or AKS managed clusters or Arc appliances.')

with self.argument_context(f"{consts.EXTENSION_NAME} extension-types list-versions") as c:
c.argument('extension_type',
help='Name of the extension type.')
c.argument('location',
validator=get_default_location_from_resource_group)
35 changes: 32 additions & 3 deletions src/k8s-extension/azext_k8s_extension/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
# --------------------------------------------------------------------------------------------

# pylint: disable=line-too-long
from azure.cli.core.commands import CliCommandType
from ._client_factory import (cf_k8s_extension, cf_k8s_extension_operation)
from ._format import k8s_extension_list_table_format, k8s_extension_show_table_format
from azure.cli.core.commands import CliCommandType, client_factory
from ._client_factory import (cf_k8s_extension, cf_k8s_extension_operation, cf_k8s_cluster_extension_types_operation, cf_k8s_cluster_extension_type_operation, cf_k8s_location_extension_types_operation, cf_k8s_extension_type_versions_operation)
from ._format import k8s_extension_list_table_format, k8s_extension_show_table_format, k8s_extension_types_list_table_format, k8s_extension_type_versions_list_table_format, k8s_extension_type_show_table_format
from . import consts


Expand All @@ -23,3 +23,32 @@ def load_command_table(self, _):
g.custom_command('list', 'list_k8s_extension', table_transformer=k8s_extension_list_table_format)
g.custom_show_command('show', 'show_k8s_extension', table_transformer=k8s_extension_show_table_format)
g.custom_command('update', 'update_k8s_extension', supports_no_wait=True)

# Subgroup - k8s-extension extension-types
k8s_cluster_extension_type_sdk = CliCommandType(
operations_tmpl=consts.EXTENSION_PACKAGE_NAME + '.vendored_sdks.operations#ClusterExtensionTypeOperations.{}',
client_factory=cf_k8s_cluster_extension_type_operation)
with self.command_group(consts.EXTENSION_NAME + " extension-types", k8s_cluster_extension_type_sdk, client_factory=cf_k8s_cluster_extension_type_operation, is_preview=True) \
as g:
g.custom_show_command('show', 'show_k8s_cluster_extension_type', table_transformer=k8s_extension_type_show_table_format)

k8s_cluster_extension_types_sdk = CliCommandType(
operations_tmpl=consts.EXTENSION_PACKAGE_NAME + '.vendored_sdks.operations.#ClusterExtensionTypesOperations.{}',
client_factory=cf_k8s_cluster_extension_types_operation)
with self.command_group(consts.EXTENSION_NAME + " extension-types", k8s_cluster_extension_types_sdk, client_factory=cf_k8s_cluster_extension_types_operation, is_preview=True) \
as g:
g.custom_command('list', 'list_k8s_cluster_extension_types', table_transformer=k8s_extension_types_list_table_format)

k8s_location_extension_types_sdk = CliCommandType(
operations_tmpl=consts.EXTENSION_PACKAGE_NAME + '.vendored_sdks.operations.#LocationExtensionTypesOperations.{}',
client_factory=cf_k8s_location_extension_types_operation)
with self.command_group(consts.EXTENSION_NAME + " extension-types", k8s_location_extension_types_sdk, client_factory=cf_k8s_location_extension_types_operation, is_preview=True) \
as g:
g.custom_command('list-by-location', 'list_k8s_location_extension_types', table_transformer=k8s_extension_types_list_table_format)

k8s_extension_type_versions_sdk = CliCommandType(
operations_tmpl=consts.EXTENSION_PACKAGE_NAME + '.vendored_sdks.operations.#ExtensionTypeVersionsOperations.{}',
client_factory=cf_k8s_extension_type_versions_operation)
with self.command_group(consts.EXTENSION_NAME + " extension-types", k8s_extension_type_versions_sdk, client_factory=cf_k8s_extension_type_versions_operation, is_preview=True) \
as g:
g.custom_command('list-versions', 'list_k8s_extension_type_versions', table_transformer=k8s_extension_type_versions_list_table_format)
2 changes: 2 additions & 0 deletions src/k8s-extension/azext_k8s_extension/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@
CONNECTED_CLUSTER_API_VERSION = "2021-10-01"
MANAGED_CLUSTER_API_VERSION = "2021-10-01"
APPLIANCE_API_VERSION = "2021-10-31-preview"

EXTENSION_TYPE_API_VERSION = "2022-01-15-preview"
48 changes: 48 additions & 0 deletions src/k8s-extension/azext_k8s_extension/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,54 @@ def delete_k8s_extension(
)


def list_k8s_extension_type_versions(cmd, client, location, extension_type):
""" List available extension type versions
"""
versions_list = client.list(location, extension_type)
return versions_list


def list_k8s_cluster_extension_types(client, resource_group_name, cluster_name, cluster_type):
""" List available extension types
"""
cluster_rp, parent_api_version = get_cluster_rp_api_version(cluster_type)
return client.list(resource_group_name, cluster_rp, cluster_type, cluster_name)


def list_k8s_location_extension_types(client, location):
""" List available extension types based on location
"""
return client.list(location)


def show_k8s_cluster_extension_type(client, resource_group_name, cluster_type, cluster_name, extension_type):
"""Get an existing Extension Type.
"""
# Determine ClusterRP
cluster_rp, parent_api_version = get_cluster_rp_api_version(cluster_type)

try:
extension_type = client.get(resource_group_name,
cluster_rp, cluster_type, cluster_name, extension_type)
return extension_type
except HttpResponseError as ex:
# Customize the error message for resources not found
if ex.response.status_code == 404:
# If Cluster not found
if ex.message.__contains__("(ResourceNotFound)"):
message = "{0} Verify that the extension type is correct and the resource exists.".format(
ex.message)
# If Configuration not found
elif ex.message.__contains__("Operation returned an invalid status code 'Not Found'"):
message = "(ExtensionNotFound) The Resource {0}/{1}/{2}/Microsoft.KubernetesConfiguration/" \
"extensions/{3} could not be found!".format(
cluster_rp, cluster_type, cluster_name, extension_type)
else:
message = ex.message
raise ResourceNotFoundError(message) from ex
raise ex


def __create_identity(cmd, resource_group_name, cluster_name, cluster_type):
subscription_id = get_subscription_id(cmd.cli_ctx)
resources = cf_resources(cmd.cli_ctx, subscription_id)
Expand Down
Loading