Skip to content
Open
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
8 changes: 8 additions & 0 deletions src/aks-preview/azext_aks_preview/_consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,3 +332,11 @@
# GPU Driver Type Consts
CONST_GPU_DRIVER_TYPE_CUDA = "CUDA"
CONST_GPU_DRIVER_TYPE_GRID = "GRID"

# aks extension constants
CONST_K8S_EXTENSION_CUSTOM_MOD_NAME = "azext_k8s_extension.custom"
CONST_K8S_EXTENSION_CLIENT_FACTORY_MOD_NAME = "azext_k8s_extension._client_factory"
CONST_K8S_EXTENSION_TYPE_CLIENT_FACTORY_MOD_NAME = "azext_k8s_extension_types._client_factory"
CONST_K8S_EXTENSION_NAME = "k8s-extension"
CONST_K8S_EXTENSION_ACTION_MOD_NAME = "azext_k8s_extension.action"
CONST_K8S_EXTENSION_FORMAT_MOD_NAME = "azext_k8s_extension._format"
73 changes: 73 additions & 0 deletions src/aks-preview/azext_aks_preview/_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,3 +373,76 @@ def _format_mesh_revision_entry(revision):
}
flattened.append(item)
return flattened


def aks_extension_list_table_format(results):
"""Format a list of K8s extensions as summary results for display with "-o table". """
return [_get_table_row(result) for result in results]


def aks_extension_show_table_format(result):
"""Format a K8s extension as summary results for display with "-o table". """
return _get_table_row(result)


def _get_table_row(result):
return OrderedDict([
('name', result['name']),
('extensionType', result.get('extensionType', '')),
('version', result.get('version', '')),
('provisioningState', result.get('provisioningState', '')),
('lastModifiedAt', result.get('systemData', {}).get('lastModifiedAt', '')),
('isSystemExtension', result.get('isSystemExtension', '')),
])


def aks_extension_types_list_table_format(results):
"""Format a list of K8s extension types as summary results for display with "-o table". """
return [_get_extension_type_table_row(result) for result in results]


def aks_extension_type_show_table_format(result):
"""Format a K8s extension type as summary results for display with "-o table". """
return _get_extension_type_table_row(result)


def _get_extension_type_table_row(result):
# Populate the values to be returned if they are not undefined
clusterTypes = ''
if result['properties']['supportedClusterTypes'] is not None:
clusterTypes = ', '.join(result['properties']['supportedClusterTypes'])

name = result['name']
defaultScope, allowMultInstances, defaultReleaseNamespace = '', '', ''
if result['properties']['supportedScopes']:
defaultScope = result['properties']['supportedScopes']['defaultScope']
if result['properties']['supportedScopes']['clusterScopeSettings'] is not None:
clusterScopeSettings = result['properties']['supportedScopes']['clusterScopeSettings']
allowMultInstances = clusterScopeSettings['allowMultipleInstances']
defaultReleaseNamespace = clusterScopeSettings['defaultReleaseNamespace']

retVal = OrderedDict([
('name', name),
('defaultScope', defaultScope),
('clusterTypes', clusterTypes),
('allowMultipleInstances', allowMultInstances),
('defaultReleaseNamespace', defaultReleaseNamespace)
])

return retVal


def aks_extension_type_versions_list_table_format(results):
"""Format a list of K8s extension type versions as summary results for display with "-o table". """
return [_get_extension_type_versions_table_row(result) for result in results]


def aks_extension_type_version_show_table_format(results):
"""Format a K8s extension type version as summary results for display with "-o table". """
return _get_extension_type_versions_table_row(results)


def _get_extension_type_versions_table_row(result):
return OrderedDict([
('versions', result['properties']['version'])
])
101 changes: 101 additions & 0 deletions src/aks-preview/azext_aks_preview/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -3301,6 +3301,107 @@
short-summary: Additional endpoint(s) to perform the connectivity check, separated by comma.
"""

helps['aks extension'] = """
type: group
short-summary: Commands to manage extensions in Kubernetes cluster
"""

helps['aks extension create'] = """
type: command
short-summary: Creates the Kubernetes extension instance on the managed cluster. Please refer to the example at the end to see how to create a k8s extension
long-summary: Create a Kubernetes Extension. \
The output includes secrets that you must protect. Be sure that you do not include these secrets in your \
source control. Also verify that no secrets are present in the logs of your command or script. \
For additional information, see http://aka.ms/clisecrets.
parameters:
- name: --extension-type -t
type: string
short-summary: Name of the extension type
- name: --cluster-name -c
type: string
short-summary: Name of the AKS cluster
- name: --name -n
type: string
short-summary: Name of the extension instance
- name: --scope
type: string
short-summary: specify scope of the extension type, takes in name or cluster as the scope
- name: --release-train
type: string
short-summary: specify the release train for the extension type
examples:
- name: Install K8s extension on AKS cluster
text: az aks extension create --resource-group my-resource-group \
--cluster-name mycluster --name myextension --extension-type microsoft.openservicemesh \
--scope cluster --release-train stable
"""

helps['aks extension update'] = """
type: command
short-summary: Update mutable properties of a Kubernetes Extension.
long-summary: For update to ConfigSettings and ConfigProtectedSettings, please \
refer to documentation of the cluster extension service to check update to these \
properties is supported before updating these properties. \
The output includes secrets that you must protect. Be sure that you do not include these secrets in your \
source control. Also verify that no secrets are present in the logs of your command or script. \
For additional information, see http://aka.ms/clisecrets.
parameters:
- name: --cluster-name -c
type: string
short-summary: Name of the AKS cluster
- name: --name -n
type: string
short-summary: Name of the extension instance
- name: --release-train
type: string
short-summary: specify the release train for the extension type
- name: --version
type: string
short-summary: Specify the version to install for the extension instance if --auto-upgrade-minor-version is not enabled.
examples:
- name: Update K8s extension on AKS cluster
text: az aks extension update --resource-group my-resource-group \
--cluster-name mycluster --name myextension --auto-upgrade true/false \
--version extension-version --release-train stable \
--configuration-settings settings-key=settings-value \
--config-protected-settings protected-settings-key=protected-value \
--config-settings-file=config-settings-file \
--config-protected-file=protected-settings-file
"""

helps['aks extension delete'] = """
type: command
short-summary: Delete a Kubernetes Extension.
parameters:
- name: --cluster-name -c
type: string
short-summary: Name of the AKS cluster
- name: --name -n
type: string
short-summary: Name of the extension instance
examples:
- name: Delete an existing Kubernetes extension on AKS cluster
text: az aks extension delete --resource-group resource-group --cluster-name cluster --name ext
"""

helps['aks extension show'] = """
type: command
short-summary: Show a Kubernetes Extension
long-summary: Show a Kubernetes Extension including its properties. \
The output includes secrets that you must protect. Be sure that you do not include these secrets in your \
source control. Also verify that no secrets are present in the logs of your command or script. \
For additional information, see http://aka.ms/clisecrets.
parameters:
- name: --cluster-name -c
type: string
short-summary: Name of the AKS cluster
- name: --name -n
type: string
short-summary: Name of the extension instance
examples:
- name: Show details of a Kubernetes Extension
text: az aks extension show --resource-group my-resource-group \
--cluster-name mycluster --name myextension
helps['aks loadbalancer'] = """
type: group
short-summary: Commands to manage load balancer configurations in a managed Kubernetes cluster.
Expand Down
25 changes: 24 additions & 1 deletion src/aks-preview/azext_aks_preview/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@

from azext_aks_preview._consts import (
ADDONS,
CONST_MONITORING_ADDON_NAME
CONST_MONITORING_ADDON_NAME,
CONST_K8S_EXTENSION_NAME,
)

from azure.cli.command_modules.acs._helpers import map_azure_error_to_cli_error
Expand All @@ -28,6 +29,7 @@
FileOperationError,
InvalidArgumentValueError,
ResourceNotFoundError,
UnknownError,
)
from azure.core.exceptions import AzureError
from knack.log import get_logger
Expand Down Expand Up @@ -395,3 +397,24 @@ def filter_hard_taints(node_initialization_taints: List[str]) -> List[str]:
# If the taint doesn't have a recognizable format, keep it, if it's incorrect - AKS-RP will return an error
filtered_taints.append(taint)
return filtered_taints


def get_k8s_extension_module(module_name):
try:
# adding the installed extension in the path
from azure.cli.core.extension.operations import add_extension_to_path
add_extension_to_path(CONST_K8S_EXTENSION_NAME)
# import the extension module
from importlib import import_module
azext_custom = import_module(module_name)
return azext_custom
except ImportError:
raise UnknownError( # pylint: disable=raise-missing-from
"Please add CLI extension `k8s-extension` for performing K8s extension operations.\n"
"Run command `az extension add --name k8s-extension`"
)


def check_if_extension_type_is_in_allow_list(extension_type_name):
allowedListOfExtensions = ["microsoft.dataprotection.kubernetes", "microsoft.flux"]
return extension_type_name.lower() in allowedListOfExtensions
107 changes: 107 additions & 0 deletions src/aks-preview/azext_aks_preview/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
tags_type,
zones_type,
)
from azure.cli.core.commands.validators import get_default_location_from_resource_group
from azext_aks_preview._client_factory import CUSTOM_MGMT_AKS_PREVIEW
from azext_aks_preview._completers import (
get_k8s_upgrades_completion_list,
Expand Down Expand Up @@ -131,6 +132,7 @@
CONST_GPU_DRIVER_TYPE_CUDA,
CONST_GPU_DRIVER_TYPE_GRID,
)

from azext_aks_preview._validators import (
validate_acr,
validate_addon,
Expand Down Expand Up @@ -218,6 +220,12 @@
CONST_STORAGE_POOL_OPTION_NVME,
CONST_STORAGE_POOL_OPTION_SSD,
)

from .action import (
AddConfigurationSettings,
AddConfigurationProtectedSettings,
)

from knack.arguments import CLIArgumentType

# candidates for enumeration
Expand Down Expand Up @@ -2325,6 +2333,105 @@ def load_arguments(self, _):
help='Space-separated additional endpoint(s) to perform the connectivity check.',
validator=validate_custom_endpoints)

# Reference: https://learn.microsoft.com/en-us/cli/azure/k8s-extension?view=azure-cli-latest
with self.argument_context('aks extension') as c:
c.argument('resource_group_name',
options_list=['--resource-group', '-g'],
help='Name of resource group.')
c.argument('location',
validator=get_default_location_from_resource_group)
c.argument('name',
options_list=['--name', '-n'],
help='Name of the extension instance')
c.argument('extension_type',
options_list=['--extension-type', '-t'],
help='Name of the extension type.')
c.argument('cluster_name',
options_list=['--cluster-name', '-c'],
help='Name of the Kubernetes cluster')
c.argument('scope',
arg_type=get_enum_type(['cluster', 'namespace']),
help='Specify the extension scope.')
c.argument('auto_upgrade_minor_version',
arg_group="Version",
options_list=['--auto-upgrade-minor-version', '--auto-upgrade'],
arg_type=get_three_state_flag(),
help='Automatically upgrade minor version of the extension instance.')
c.argument('version',
arg_group="Version",
help='Specify the version to install for the extension instance if'
' --auto-upgrade-minor-version is not enabled.')
c.argument('release_train',
arg_group="Version",
help='Specify the release train for the extension type.')
c.argument('configuration_settings',
arg_group="Configuration",
options_list=['--configuration-settings', '--config'],
action=AddConfigurationSettings,
nargs='+',
help='Configuration Settings as key=value pair.'
+ 'Repeat parameter for each setting.'
+ 'Do not use this for secrets, as this value is returned in response.')
c.argument('configuration_protected_settings',
arg_group="Configuration",
options_list=['--config-protected-settings', '--config-protected'],
action=AddConfigurationProtectedSettings,
nargs='+',
help='Configuration Protected Settings as key=value pair.'
+ 'Repeat parameter for each setting. Only the key is returned in response, the value is not.')
c.argument('configuration_settings_file',
arg_group="Configuration",
options_list=['--config-settings-file', '--config-file'],
help='JSON file path for configuration-settings')
c.argument('configuration_protected_settings_file',
arg_group="Configuration",
options_list=['--config-protected-settings-file', '--config-protected-file'],
help='JSON file path for configuration-protected-settings')
c.argument('release_namespace',
help='Specify the namespace to install the extension release.')
c.argument('target_namespace',
help='Specify the target namespace to install to for the extension instance. This'
' parameter is required if extension scope is set to \'namespace\'')

with self.argument_context("aks extension update") as c:
c.argument('yes',
options_list=['--yes', '-y'],
help='Ignore confirmation prompts')

with self.argument_context("aks extension delete") as c:
c.argument('yes',
options_list=['--yes', '-y'],
help='Ignore confirmation prompts')
c.argument('force',
help='Specify whether to force delete the extension from the cluster.')

# Reference: https://learn.microsoft.com/en-us/cli/azure/k8s-extension/extension-types?view=azure-cli-latest
with self.argument_context("aks extension-type") as c:
c.argument('resource_group_name',
options_list=['--resource-group', '-g'],
help='Name of resource group.')
c.argument('cluster_name',
options_list=['--cluster-name', '-c'],
help='Name of the Kubernetes cluster')
c.argument('extension_type',
options_list=['--extension-type', '-t'],
help='Name of the extension type.')
c.argument('location',
validator=get_default_location_from_resource_group,
help='Name of the location. Values from: `az account list-locations`')
c.argument('version',
help='Version for the extension type.')
c.argument('major_version',
help='Filter results by only the major version of an extension type.'
+ 'For example if 1 is specified, all versions with major version 1 (1.1, 1.1.2) will be shown.'
+ 'The default value is None')
c.argument('release_train',
arg_group="Version",
help='Specify the release train for the extension type.')
c.argument('show_latest',
arg_type=get_three_state_flag(),
help='Filter results by only the latest version.'
+ 'For example, if this flag is used the latest version of the extensionType will be shown.')
# AKS loadbalancer command parameter configuration
with self.argument_context("aks loadbalancer add") as c:
c.argument(
Expand Down
Loading
Loading