Skip to content

Commit

Permalink
Custom User Confirmation for Partners (Azure#70)
Browse files Browse the repository at this point in the history
* Custom user confirmation

* Check for disable confirm prompty for confirmation

* Add yes to delete command
  • Loading branch information
jonathan-innis authored Aug 24, 2021
1 parent 3a293ed commit 7deb020
Show file tree
Hide file tree
Showing 11 changed files with 65 additions and 73 deletions.
40 changes: 31 additions & 9 deletions src/k8s-extension/azext_k8s_extension/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,47 @@

helps[f'{consts.EXTENSION_NAME}'] = """
type: group
short-summary: Commands to manage K8s-extensions.
short-summary: Commands to manage Kubernetes Extensions.
"""

helps[f'{consts.EXTENSION_NAME} create'] = """
helps[f'{consts.EXTENSION_NAME} create'] = f"""
type: command
short-summary: Create a K8s-extension.
short-summary: Create a Kubernetes Extension.
examples:
- name: Create a Kubernetes Extension
text: |-
az {consts.EXTENSION_NAME} create --resource-group my-resource-group \\
--cluster-name mycluster --cluster-type connectedClusters \\
--name myextension --extension-type microsoft.openservicemesh \\
--scope cluster --release-train stable
"""

helps[f'{consts.EXTENSION_NAME} list'] = """
helps[f'{consts.EXTENSION_NAME} list'] = f"""
type: command
short-summary: List K8s-extensions.
short-summary: List Kubernetes Extensions.
examples:
- name: List all Kubernetes Extensions on a cluster
text: |-
az {consts.EXTENSION_NAME} list --resource-group my-resource-group \\
--cluster-name mycluster --cluster-type connectedClusters
"""

helps[f'{consts.EXTENSION_NAME} delete'] = """
helps[f'{consts.EXTENSION_NAME} delete'] = f"""
type: command
short-summary: Delete a K8s-extension.
short-summary: Delete a Kubernetes Extension.
examples:
- name: Delete an existing Kubernetes Extension
text: |-
az {consts.EXTENSION_NAME} delete --resource-group my-resource-group \\
--cluster-name mycluster --cluster-type connectedClusters --name myextension
"""

helps[f'{consts.EXTENSION_NAME} show'] = """
helps[f'{consts.EXTENSION_NAME} show'] = f"""
type: command
short-summary: Show details of a K8s-extension.
short-summary: Show a Kubernetes Extension.
examples:
- name: Show details of a Kubernetes Extension
text: |-
az {consts.EXTENSION_NAME} show --resource-group my-resource-group \\
--cluster-name mycluster --cluster-type connectedClusters --name myextension
"""
5 changes: 5 additions & 0 deletions src/k8s-extension/azext_k8s_extension/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,8 @@ def load_arguments(self, _):
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(f"{consts.EXTENSION_NAME} delete") as c:
c.argument('yes',
options_list=['--yes', '-y'],
help='Ignore confirmation prompts')
2 changes: 1 addition & 1 deletion src/k8s-extension/azext_k8s_extension/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ def load_command_table(self, _):
is_preview=True) \
as g:
g.custom_command('create', 'create_k8s_extension')
g.custom_command('delete', 'delete_k8s_extension', confirmation=True)
g.custom_command('delete', 'delete_k8s_extension')
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)
6 changes: 3 additions & 3 deletions src/k8s-extension/azext_k8s_extension/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def update_k8s_extension(client, resource_group_name, cluster_type, cluster_name
# return client.update(resource_group_name, cluster_rp, cluster_type, cluster_name, name, upd_extension)


def delete_k8s_extension(client, resource_group_name, cluster_name, name, cluster_type):
def delete_k8s_extension(cmd, client, resource_group_name, cluster_name, name, cluster_type, yes=False):
"""Delete an existing Kubernetes Extension.
"""
Expand All @@ -201,12 +201,12 @@ def delete_k8s_extension(client, resource_group_name, cluster_name, name, cluste
try:
extension = client.get(resource_group_name, cluster_rp, cluster_type, cluster_name, name)
except HttpResponseError:
logger.warning("No extension with name '%s' found on cluster '%s', so nothing to delete", cluster_name, name)
logger.warning("No extension with name '%s' found on cluster '%s', so nothing to delete", name, cluster_name)
return None
extension_class = ExtensionFactory(extension.extension_type.lower())

# If there is any custom delete logic, this will call the logic
extension_class.Delete(client, resource_group_name, cluster_name, name, cluster_type)
extension_class.Delete(cmd, client, resource_group_name, cluster_name, name, cluster_type, yes)

return client.delete(resource_group_name, cluster_rp, cluster_type, cluster_name, name)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,16 @@
from knack.log import get_logger

from ..vendored_sdks.models import ExtensionInstance
from ..vendored_sdks.models import ExtensionInstanceUpdate
from ..vendored_sdks.models import ScopeCluster
from ..vendored_sdks.models import Scope

from .PartnerExtensionModel import PartnerExtensionModel
from .DefaultExtension import DefaultExtension
from .ContainerInsights import _get_container_insights_settings

logger = get_logger(__name__)


class AzureDefender(PartnerExtensionModel):
class AzureDefender(DefaultExtension):
def Create(self, cmd, client, resource_group_name, cluster_name, name, cluster_type, extension_type,
scope, auto_upgrade_minor_version, release_train, version, target_namespace,
release_namespace, configuration_settings, configuration_protected_settings,
Expand Down Expand Up @@ -59,17 +58,3 @@ def Create(self, cmd, client, resource_group_name, cluster_name, name, cluster_t
configuration_protected_settings=configuration_protected_settings
)
return extension_instance, name, create_identity

def Update(self, extension, auto_upgrade_minor_version, release_train, version):
"""ExtensionType 'microsoft.azuredefender.kubernetes' specific validations & defaults for Update
Must create and return a valid 'ExtensionInstanceUpdate' object.
"""
return ExtensionInstanceUpdate(
auto_upgrade_minor_version=auto_upgrade_minor_version,
release_train=release_train,
version=version
)

def Delete(self, client, resource_group_name, cluster_name, name, cluster_type):
pass
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import copy
from hashlib import md5
from typing import Any, Dict, List, Tuple
from azext_k8s_extension.partner_extensions.DefaultExtension import DefaultExtension

import azure.mgmt.relay
import azure.mgmt.relay.models
Expand All @@ -27,10 +28,9 @@
from msrestazure.azure_exceptions import CloudError

from .._client_factory import cf_resources
from .PartnerExtensionModel import PartnerExtensionModel
from .DefaultExtension import DefaultExtension, user_confirmation_factory
from ..vendored_sdks.models import (
ExtensionInstance,
ExtensionInstanceUpdate,
Scope,
ScopeCluster
)
Expand All @@ -41,7 +41,7 @@


# pylint: disable=too-many-instance-attributes
class AzureMLKubernetes(PartnerExtensionModel):
class AzureMLKubernetes(DefaultExtension):
def __init__(self):
# constants for configuration settings.
self.DEFAULT_RELEASE_NAMESPACE = 'azureml'
Expand Down Expand Up @@ -158,18 +158,12 @@ def Create(self, cmd, client, resource_group_name, cluster_name, name, cluster_t
)
return extension_instance, name, create_identity

def Update(self, extension, auto_upgrade_minor_version, release_train, version):
return ExtensionInstanceUpdate(
auto_upgrade_minor_version=auto_upgrade_minor_version,
release_train=release_train,
version=version
)

def Delete(self, client, resource_group_name, cluster_name, name, cluster_type):
def Delete(self, cmd, client, resource_group_name, cluster_name, name, cluster_type, yes):
# Give a warning message
logger.warning("If nvidia.com/gpu or fuse resource is not recognized by kubernetes after this deletion, "
"you probably have installed nvidia-device-plugin or fuse-device-plugin before installing AMLArc extension. "
"Please try to reinstall device plugins to fix this issue.")
user_confirmation_factory(cmd, yes)

def __validate_config(self, configuration_settings, configuration_protected_settings):
# perform basic validation of the input config
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,18 @@
from msrestazure.tools import parse_resource_id, is_valid_resource_id

from ..vendored_sdks.models import ExtensionInstance
from ..vendored_sdks.models import ExtensionInstanceUpdate
from ..vendored_sdks.models import ScopeCluster
from ..vendored_sdks.models import Scope

from .PartnerExtensionModel import PartnerExtensionModel
from .DefaultExtension import DefaultExtension

from .._client_factory import (
cf_resources, cf_resource_groups, cf_log_analytics)

logger = get_logger(__name__)


class ContainerInsights(PartnerExtensionModel):
class ContainerInsights(DefaultExtension):
def Create(self, cmd, client, resource_group_name, cluster_name, name, cluster_type, extension_type,
scope, auto_upgrade_minor_version, release_train, version, target_namespace,
release_namespace, configuration_settings, configuration_protected_settings,
Expand Down Expand Up @@ -71,20 +70,6 @@ def Create(self, cmd, client, resource_group_name, cluster_name, name, cluster_t
)
return extension_instance, name, create_identity

def Update(self, extension, auto_upgrade_minor_version, release_train, version):
"""ExtensionType 'microsoft.azuremonitor.containers' specific validations & defaults for Update
Must create and return a valid 'ExtensionInstanceUpdate' object.
"""
return ExtensionInstanceUpdate(
auto_upgrade_minor_version=auto_upgrade_minor_version,
release_train=release_train,
version=version
)

def Delete(self, client, resource_group_name, cluster_name, name, cluster_type):
pass


# Custom Validation Logic for Container Insights

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

# pylint: disable=unused-argument

from azure.cli.core.util import user_confirmation

from ..vendored_sdks.models import ExtensionInstance
from ..vendored_sdks.models import ExtensionInstanceUpdate
from ..vendored_sdks.models import ScopeCluster
Expand Down Expand Up @@ -56,5 +58,11 @@ def Update(self, extension, auto_upgrade_minor_version, release_train, version):
version=version
)

def Delete(self, client, resource_group_name, cluster_name, name, cluster_type):
pass
def Delete(self, cmd, client, resource_group_name, cluster_name, name, cluster_type, yes):
user_confirmation_factory(cmd, yes)


def user_confirmation_factory(cmd, yes, message="Are you sure you want to perform this operation?"):
if cmd.cli_ctx.config.getboolean('core', 'disable_confirm_prompt', fallback=False):
return
user_confirmation(message, yes=yes)
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
from ..vendored_sdks.models import ScopeNamespace
from ..vendored_sdks.models import Scope

from .PartnerExtensionModel import PartnerExtensionModel
from .DefaultExtension import DefaultExtension


class DefaultExtensionWithIdentity(PartnerExtensionModel):
class DefaultExtensionWithIdentity(DefaultExtension):
def Create(self, cmd, client, resource_group_name, cluster_name, name, cluster_type, extension_type,
scope, auto_upgrade_minor_version, release_train, version, target_namespace,
release_namespace, configuration_settings, configuration_protected_settings,
Expand Down Expand Up @@ -55,6 +55,3 @@ def Update(self, extension, auto_upgrade_minor_version, release_train, version):
release_train=release_train,
version=version
)

def Delete(self, client, resource_group_name, cluster_name, name, cluster_type):
pass
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# pylint: disable=redefined-outer-name
# pylint: disable=no-member

from azext_k8s_extension.partner_extensions.DefaultExtension import DefaultExtension
from knack.log import get_logger

from azure.cli.core.azclierror import InvalidArgumentValueError
Expand All @@ -16,9 +17,7 @@
import yaml
import requests

from ..partner_extensions import PartnerExtensionModel

from .PartnerExtensionModel import PartnerExtensionModel
from .DefaultExtension import DefaultExtension

from ..vendored_sdks.models import (
ExtensionInstance,
Expand All @@ -32,7 +31,7 @@
logger = get_logger(__name__)


class OpenServiceMesh(PartnerExtensionModel):
class OpenServiceMesh(DefaultExtension):

def Create(self, cmd, client, resource_group_name, cluster_name, name, cluster_type, extension_type,
scope, auto_upgrade_minor_version, release_train, version, target_namespace,
Expand Down Expand Up @@ -90,9 +89,6 @@ def Update(self, extension, auto_upgrade_minor_version, release_train, version):
version=version
)

def Delete(self, client, resource_group_name, cluster_name, name, cluster_type):
pass


def _validate_tested_distro(cmd, cluster_resource_group_name, cluster_name, extension_version):

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ def Update(self, extension: ExtensionInstance, auto_upgrade_minor_version: bool,
pass

@abstractmethod
def Delete(self, client, resource_group_name: str, cluster_name: str, name: str, cluster_type: str):
def Delete(self, cmd, client, resource_group_name: str, cluster_name: str, name: str, cluster_type: str, yes: bool):
pass

0 comments on commit 7deb020

Please sign in to comment.