Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added custom input paramter and validation for backupagent extension #131

Closed
Closed
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/azext_k8s_extension/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@
CONNECTED_CLUSTER_RP = "Microsoft.Kubernetes"
MANAGED_CLUSTER_RP = "Microsoft.ContainerService"
APPLIANCE_RP = "Microsoft.ResourceConnector"
PROVISIONED_CLUSTER_RP = "Microsoft.HybridContainerService"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is being added separately by @NarayanThiru in a separate PR for provisionedClusters, do you require provisionedClusters RP to be part of the this PR?


CONNECTED_CLUSTER_TYPE = "connectedclusters"
MANAGED_CLUSTER_TYPE = "managedclusters"
APPLIANCE_TYPE = "appliances"
PROVISIONED_CLUSTER_TYPE = "provisionedClusters"


CONNECTED_CLUSTER_API_VERSION = "2021-10-01"
MANAGED_CLUSTER_API_VERSION = "2021-10-01"
APPLIANCE_API_VERSION = "2021-10-31-preview"
PROVISIONED_CLUSTER_API_VERSION = "2021-09-01"
2 changes: 2 additions & 0 deletions src/k8s-extension/azext_k8s_extension/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from .partner_extensions.OpenServiceMesh import OpenServiceMesh
from .partner_extensions.AzureMLKubernetes import AzureMLKubernetes
from .partner_extensions.Dapr import Dapr
from .partner_extensions.BackupAgent import AzureBackupAgent
from .partner_extensions.DefaultExtension import (
DefaultExtension,
user_confirmation_factory,
Expand All @@ -47,6 +48,7 @@ def ExtensionFactory(extension_name):
"microsoft.openservicemesh": OpenServiceMesh,
"microsoft.azureml.kubernetes": AzureMLKubernetes,
"microsoft.dapr": Dapr,
"microsoft.azurebackup.backupagent": AzureBackupAgent,
}

# Return the extension if we find it in the map, else return the default
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

# pylint: disable=unused-argument

import datetime
import json

from ..utils import get_cluster_rp_api_version

from knack.log import get_logger

from azure.cli.core.azclierror import InvalidArgumentValueError
from azure.cli.core.commands.client_factory import get_subscription_id
from msrestazure.azure_exceptions import CloudError

from ..vendored_sdks.models import Extension

from .DefaultExtension import DefaultExtension

from .._client_factory import (
cf_resources)

logger = get_logger(__name__)


class AzureBackupAgent(DefaultExtension):
def __init__(self):
# constants for configuration settings.
self.DEFAULT_RELEASE_NAMESPACE = 'backupagent-ns'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This default release namespace is part of the extension registration so it is not required to be statically coded into the CLI


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,
configuration_settings_file, configuration_protected_settings_file):
# get the arc's location
subscription_id = get_subscription_id(cmd.cli_ctx)
cluster_rp, parent_api_version = get_cluster_rp_api_version(cluster_type)
cluster_resource_id = '/subscriptions/{0}/resourceGroups/{1}/providers/{2}' \
'/{3}/{4}'.format(subscription_id, resource_group_name, cluster_rp, cluster_type, cluster_name)
cluster_location = ''
resources = cf_resources(cmd.cli_ctx, subscription_id)
try:
resource = resources.get_by_id(
cluster_resource_id, parent_api_version)
cluster_location = resource.location.lower()
except CloudError as ex:
raise ex

# generate values for the extension if none is set.
configuration_settings['clusterArmID'] = configuration_settings.get('cluster_name', cluster_resource_id)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This data is coming through Extension Metadata as described here: https://msazure.visualstudio.com/One/_wiki/wikis/One.wiki/142401/Extension-Metadata so there is no need to pass this through the configuration_settings this way

configuration_settings['extension_name'] = configuration_settings.get('extension_name', name)
configuration_settings['location'] = configuration_settings.get('location', cluster_location)

create_identity = True
extension = Extension(
extension_type=extension_type,
auto_upgrade_minor_version=auto_upgrade_minor_version,
release_train=release_train,
target_namespace=target_namespace,
version=version,
scope=scope,
configuration_settings=configuration_settings,
configuration_protected_settings=configuration_protected_settings,
)
return extension, name, create_identity
2 changes: 2 additions & 0 deletions src/k8s-extension/azext_k8s_extension/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ def get_cluster_rp_api_version(cluster_type) -> Tuple[str, str]:
return consts.CONNECTED_CLUSTER_RP, consts.CONNECTED_CLUSTER_API_VERSION
if cluster_type.lower() == consts.APPLIANCE_TYPE:
return consts.APPLIANCE_RP, consts.APPLIANCE_API_VERSION
if cluster_type.lower() == consts.PROVISIONED_CLUSTER_TYPE:
return consts.PROVISIONED_CLUSTER_RP, consts.PROVISIONED_CLUSTER_API_VERSION
if (
cluster_type.lower() == ""
or cluster_type.lower() == consts.MANAGED_CLUSTER_TYPE
Expand Down
108 changes: 108 additions & 0 deletions testing/test/extensions/public/BackupAgent.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
Describe 'Backup Agent Testing' {
BeforeAll {
$extensionType = "microsoft.azurebackup.backupagent"
$extensionName = "microsoft-azure-backupagent"
$extensionAgentNamespace = "backupagent-ns"
$storagaccountname = "backupagenttestsa"

. $PSScriptRoot/../../helper/Constants.ps1
. $PSScriptRoot/../../helper/Helper.ps1
}
It 'Creating storage account required as input to extension!' {
az storage account create -n $storagaccountname -g $($ENVCONFIG.resourceGroup) -l eastus --sku Standard_LRS
$? | Should -BeTrue
}
It 'Creates the extension and checks that it onboards correctly' {
az $Env:K8sExtensionName create -c $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --cluster-type connectedClusters --extension-type $extensionType -n $extensionName --configuration-settings fluentbit.LogStorageAccountName=$storagaccountname StoragAccount.baseuri=https://management.azure.com BAconfigMapOverrides.storageaccount=$storagaccountname StoragAccount.resourceId=/subscriptions/$($ENVCONFIG.subscriptionId)/resourceGroups/$($ENVCONFIG.resourceGroup)/providers/Microsoft.Storage/storageAccounts/$storagaccountname
$? | Should -BeTrue

$output = az $Env:K8sExtensionName show -c $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --cluster-type connectedClusters -n $extensionName
$? | Should -BeTrue

$isAutoUpgradeMinorVersion = ($output | ConvertFrom-Json).autoUpgradeMinorVersion
$isAutoUpgradeMinorVersion.ToString() -eq "True" | Should -BeTrue

# Check that we get the principal id back for the created identity
$principalId = ($output | ConvertFrom-Json).identity.principalId
$principalId | Should -Not -BeNullOrEmpty

# Loop and retry until the extension installs
$n = 0
do
{
# Only check the extension config, not the pod since this doesn't bring up pods
$output = az $Env:K8sExtensionName show -c $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --cluster-type connectedClusters -n $extensionName
$provisioningState = ($output | ConvertFrom-Json).provisioningState
Write-Host "Got ProvisioningState: $provisioningState for the extension"
if ((Has-ExtensionData $extensionName) -And ($provisioningState -eq "Succeeded")) {
break
}
Start-Sleep -Seconds 10
$n += 1
} while ($n -le 20)
$n | Should -BeLessOrEqual 20
}

It "Performs a show on the extension" {
$output = az $Env:K8sExtensionName show -c $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --cluster-type connectedClusters -n $extensionName
$? | Should -BeTrue
$output | Should -Not -BeNullOrEmpty
}

It "Runs an update on the extension on the cluster" {
$output = az $Env:K8sExtensionName update -c $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --cluster-type connectedClusters -n $extensionName --auto-upgrade false --no-wait
$? | Should -BeTrue

$output = az $Env:K8sExtensionName show -c $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --cluster-type connectedClusters -n $extensionName
$? | Should -BeTrue

$isAutoUpgradeMinorVersion = ($output | ConvertFrom-Json).autoUpgradeMinorVersion
$isAutoUpgradeMinorVersion.ToString() -eq "False" | Should -BeTrue

# Loop and retry until the extension config updates
$n = 0
do
{
$isAutoUpgradeMinorVersion = (Get-ExtensionData $extensionName).spec.autoUpgradeMinorVersion
if (!$isAutoUpgradeMinorVersion) { #autoUpgradeMinorVersion doesn't exist in ExtensionConfig CRD if false
break
}
Start-Sleep -Seconds 10
$n += 1
} while ($n -le $MAX_RETRY_ATTEMPTS)
$n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS
}

It "Lists the extensions on the cluster" {
$output = az $Env:K8sExtensionName list -c $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --cluster-type connectedClusters
$? | Should -BeTrue

$output | Should -Not -BeNullOrEmpty
$extensionExists = $output | ConvertFrom-Json | Where-Object { $_.extensionType -eq $extensionType }
$extensionExists | Should -Not -BeNullOrEmpty
}

It "Deletes the extension from the cluster" {
$output = az $Env:K8sExtensionName delete -c $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --cluster-type connectedClusters -n $extensionName --force
$? | Should -BeTrue

# Extension should not be found on the cluster
$output = az $Env:K8sExtensionName show -c $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --cluster-type connectedClusters -n $extensionName
$? | Should -BeFalse
$output | Should -BeNullOrEmpty
}

It "Delete storage account used as input to extension" {
az storage account delete -n $storagaccountname -g $($ENVCONFIG.resourceGroup)
$? | Should -BeTrue
}

It "Performs another list after the delete" {
$output = az $Env:K8sExtensionName list -c $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --cluster-type connectedClusters
$? | Should -BeTrue
$output | Should -Not -BeNullOrEmpty

$extensionExists = $output | ConvertFrom-Json | Where-Object { $_.extensionType -eq $extensionName }
$extensionExists | Should -BeNullOrEmpty
}
}