diff --git a/src/connectedk8s/azext_connectedk8s/_client_factory.py b/src/connectedk8s/azext_connectedk8s/_client_factory.py index bc1b613fd9f..0a795ec9c92 100644 --- a/src/connectedk8s/azext_connectedk8s/_client_factory.py +++ b/src/connectedk8s/azext_connectedk8s/_client_factory.py @@ -83,7 +83,6 @@ def cf_connectedk8s_prev_2025_08_01( KubernetesClient, subscription_id=os.getenv("AZURE_SUBSCRIPTION_ID"), credential=credential, - base_url="https://management.azure.com", per_call_policies=[headers_policy], ) return client @@ -91,7 +90,6 @@ def cf_connectedk8s_prev_2025_08_01( client = get_mgmt_service_client( cli_ctx, KubernetesClient, - base_url="https://management.azure.com", per_call_policies=[headers_policy], ) return client diff --git a/src/connectedk8s/azext_connectedk8s/_precheckutils.py b/src/connectedk8s/azext_connectedk8s/_precheckutils.py index b10c9a22241..231f2b4c659 100644 --- a/src/connectedk8s/azext_connectedk8s/_precheckutils.py +++ b/src/connectedk8s/azext_connectedk8s/_precheckutils.py @@ -212,7 +212,7 @@ def executing_cluster_diagnostic_checks_job( ) return None - mcr_url = azext_utils.get_mcr_path(cmd) + mcr_url = azext_utils.get_mcr_path(cmd.cli_ctx.cloud.endpoints.active_directory) chart_path = azext_utils.get_chart_path( f"{mcr_url}/{consts.Cluster_Diagnostic_Checks_Job_Registry_Path}", diff --git a/src/connectedk8s/azext_connectedk8s/_utils.py b/src/connectedk8s/azext_connectedk8s/_utils.py index 6717ed907c1..e3268806f7b 100644 --- a/src/connectedk8s/azext_connectedk8s/_utils.py +++ b/src/connectedk8s/azext_connectedk8s/_utils.py @@ -58,11 +58,15 @@ # pylint: disable=bare-except -def get_mcr_path(cmd: CLICommand) -> str: - active_directory_array = cmd.cli_ctx.cloud.endpoints.active_directory.split(".") +def get_mcr_path(active_directory_endpoint: str) -> str: + active_directory_array = active_directory_endpoint.split(".") - # default for public, mc, ff clouds - mcr_postfix = active_directory_array[2] + # For US Government and China clouds, use public mcr + if active_directory_endpoint.endswith((".us", ".cn")): + return "mcr.microsoft.com" + + # Default MCR postfix + mcr_postfix = "com" # special cases for USSec, exclude part of suffix if len(active_directory_array) == 4 and active_directory_array[2] == "microsoft": mcr_postfix = active_directory_array[3] diff --git a/src/connectedk8s/azext_connectedk8s/clientproxyhelper/_binaryutils.py b/src/connectedk8s/azext_connectedk8s/clientproxyhelper/_binaryutils.py index c655b4269de..5097fb952cc 100644 --- a/src/connectedk8s/azext_connectedk8s/clientproxyhelper/_binaryutils.py +++ b/src/connectedk8s/azext_connectedk8s/clientproxyhelper/_binaryutils.py @@ -76,7 +76,7 @@ def _download_proxy_from_MCR( operating_system: str, architecture: str, ) -> None: - mcr_url = utils.get_mcr_path(cmd) + mcr_url = utils.get_mcr_path(cmd.cli_ctx.cloud.endpoints.active_directory) mar_target = f"{mcr_url}/{consts.CLIENT_PROXY_MCR_TARGET}/{operating_system.lower()}/{architecture}/arc-proxy" logger.debug( diff --git a/src/connectedk8s/azext_connectedk8s/custom.py b/src/connectedk8s/azext_connectedk8s/custom.py index c5ed8ed8ec9..d90c0c760c0 100644 --- a/src/connectedk8s/azext_connectedk8s/custom.py +++ b/src/connectedk8s/azext_connectedk8s/custom.py @@ -1318,7 +1318,7 @@ def install_helm_client(cmd: CLICommand) -> str: "Downloading helm client for first time. This can take few minutes..." ) - mcr_url = utils.get_mcr_path(cmd) + mcr_url = utils.get_mcr_path(cmd.cli_ctx.cloud.endpoints.active_directory) client = oras.client.OrasClient(hostname=mcr_url) retry_count = 3 diff --git a/src/connectedk8s/azext_connectedk8s/tests/unittests/test_utils_.py b/src/connectedk8s/azext_connectedk8s/tests/unittests/test_utils_.py index 768290b902a..32d1da1e3b4 100644 --- a/src/connectedk8s/azext_connectedk8s/tests/unittests/test_utils_.py +++ b/src/connectedk8s/azext_connectedk8s/tests/unittests/test_utils_.py @@ -9,6 +9,7 @@ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../.."))) from azext_connectedk8s._utils import ( + get_mcr_path, process_helm_error_detail, redact_sensitive_fields_from_string, remove_rsa_private_key, @@ -76,5 +77,27 @@ def test_redact_sensitive_fields_from_string(): ) +def test_get_mcr_path(): + input_active_directory = "login.microsoftonline.com" + expected_output = "mcr.microsoft.com" + assert get_mcr_path(input_active_directory) == expected_output + + input_active_directory = "login.microsoftonline.us" + expected_output = "mcr.microsoft.com" + assert get_mcr_path(input_active_directory) == expected_output + + input_active_directory = "login.chinacloudapi.cn" + expected_output = "mcr.microsoft.com" + assert get_mcr_path(input_active_directory) == expected_output + + input_active_directory = "https://login.microsoftonline.microsoft.foo" + expected_output = "mcr.microsoft.foo" + assert get_mcr_path(input_active_directory) == expected_output + + input_active_directory = "https://login.microsoftonline.some.cloud.bar" + expected_output = "mcr.microsoft.some.cloud.bar" + assert get_mcr_path(input_active_directory) == expected_output + + if __name__ == "__main__": pytest.main() diff --git a/src/k8s-extension/azext_k8s_extension/custom.py b/src/k8s-extension/azext_k8s_extension/custom.py index f7626d06e58..6122ea61224 100644 --- a/src/k8s-extension/azext_k8s_extension/custom.py +++ b/src/k8s-extension/azext_k8s_extension/custom.py @@ -763,7 +763,7 @@ def install_helm_client(cmd: CLICommand) -> str: "Downloading helm client for first time. This can take few minutes..." ) - mcr_url = utils.get_mcr_path(cmd) + mcr_url = utils.get_mcr_path(cmd.cli_ctx.cloud.endpoints.active_directory) client = oras.client.OrasClient(hostname=mcr_url) retry_count = 3 diff --git a/src/k8s-extension/azext_k8s_extension/utils.py b/src/k8s-extension/azext_k8s_extension/utils.py index 767550ccef8..345d92f9016 100644 --- a/src/k8s-extension/azext_k8s_extension/utils.py +++ b/src/k8s-extension/azext_k8s_extension/utils.py @@ -361,11 +361,15 @@ def create_folder_diagnosticlogs(folder_name: str, base_folder_name: str) -> tup ) return "", False -def get_mcr_path(cmd: CLICommand) -> str: - active_directory_array = cmd.cli_ctx.cloud.endpoints.active_directory.split(".") +def get_mcr_path(active_directory_endpoint: str) -> str: + active_directory_array = active_directory_endpoint.split(".") - # default for public, mc, ff clouds - mcr_postfix = active_directory_array[2] + # For US Government and China clouds, use public mcr + if active_directory_endpoint.endswith((".us", ".cn")): + return "mcr.microsoft.com" + + # Default MCR postfix + mcr_postfix = "com" # special cases for USSec, exclude part of suffix if len(active_directory_array) == 4 and active_directory_array[2] == "microsoft": mcr_postfix = active_directory_array[3] diff --git a/testing/.gitignore b/testing/.gitignore new file mode 100644 index 00000000000..29f33294b8b --- /dev/null +++ b/testing/.gitignore @@ -0,0 +1,9 @@ +settings.json +tmp/ +bin/* +!bin/connectedk8s-1.0.0-py3-none-any.whl +!bin/k8s_extension-0.3.0-py3-none-any.whl +!bin/k8s_extension_private-0.1.0-py3-none-any.whl +!bin/k8s_configuration-1.0.0-py3-none-any.whl +!bin/connectedk8s-values.yaml +*.xml \ No newline at end of file diff --git a/testing/Bootstrap.ps1 b/testing/Bootstrap.ps1 new file mode 100644 index 00000000000..ad21cfddad2 --- /dev/null +++ b/testing/Bootstrap.ps1 @@ -0,0 +1,30 @@ +param ( + [switch] $SkipInstall, + [switch] $CI +) + +# Disable confirm prompt for script +az config set core.disable_confirm_prompt=true + +# Configuring the environment +$ENVCONFIG = Get-Content -Path $PSScriptRoot/settings.json | ConvertFrom-Json + +az account set --subscription $ENVCONFIG.subscriptionId + +if (-not (Test-Path -Path $PSScriptRoot/tmp)) { + New-Item -ItemType Directory -Path $PSScriptRoot/tmp +} + +az group show --name $envConfig.resourceGroup +if (!$?) { + Write-Host "Resource group does not exist, creating it now in region 'eastus2euap'" + az group create --name $envConfig.resourceGroup --location eastus2euap + + if (!$?) { + Write-Host "Failed to create Resource Group - exiting!" + Exit 1 + } +} + + +Copy-Item $HOME/.kube/config -Destination $PSScriptRoot/tmp/KUBECONFIG \ No newline at end of file diff --git a/testing/README.md b/testing/README.md new file mode 100644 index 00000000000..33f12b5b1a3 --- /dev/null +++ b/testing/README.md @@ -0,0 +1,116 @@ +# K8s Partner Extension Test Suite + +This repository serves as the integration testing suite for the `k8s-extension` Azure CLI module. + +## Testing Requirements + +All partners who wish to merge their __Custom Private Preview Release__ (owner: _Partner_) into the __Official Private Preview Release__ are required to author additional integration tests for their extension to ensure that their extension will continue to function correctly as more extensions are added into the __Official Private Preview Release__. + +For more information on creating these tests, see [Authoring Tests](docs/test_authoring.md) + +## Pre-Requisites + +In order to properly test all regression tests within the test suite, you must onboard an AKS cluster which you will use to generate your Azure Arc resource to test the extensions. Ensure that you have a resource group where you can onboard this cluster. + +### Required Installations + +The following installations are required in your environment for the integration tests to run correctly: + +1. [Helm 3](https://helm.sh/docs/intro/install/) +2. [Kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) +3. [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) + +## Setup + +### Step 1: Install Pester + +This project contains [Pester](https://pester.dev/) test framework commands that are required for the integration tests to run. In an admin powershell terminal, run + +```powershell +Install-Module Pester -Force -SkipPublisherCheck +Import-Module Pester -PassThru +``` + +If you run into issues installing the framework, refer to the [Installation Guide](https://pester.dev/docs/introduction/installation) provided by the Pester docs. + +### Step 2: Get Test suite files + +You can either clone this repo (preferred option, since you will be adding your tests to this suite) or copy the files in this repo locally. Rest of the instructions here assume your working directory is k8spartner-extension-testing. + +### Step 3: Update the `k8s-extension`/`k8s-extension-private` .whl package + +This integration test suite references the .whl packages found in the `\bin` directory. After generating your `k8s-extension`/`k8s-extension-private` .whl package, copy your updated package into the `\bin` directory. + +### Step 4: Create a `settings.json` + +To onboard the AKS and Arc clusters correctly, you will need to create a `settings.json` configuration. Create a new `settings.json` file by copying the contents of the `settings.template.json` into this file. Update the subscription id, resource group, and AKS and Arc cluster name fields with your specific values. + +### Step 5: Update the extension version value in `settings.json` + +To ensure that the tests point to your `k8s-extension-private` `.whl` package, change the value of the `k8s-extension-private` to match your package versioning in the format (Major.Minor.Patch.Extension). For example, the `k8s_extension_private-0.1.0.openservicemesh_5-py3-none-any.whl` whl package would have extension versions set to +```json +{ + "k8s-extension": "0.1.0", + "k8s-extension-private": "0.1.0.openservicemesh_5", + "connectedk8s": "0.3.5" +} + +``` + +_Note: Updates to the `connectedk8s` version and `k8s-extension` version can also be made by adding a different version of the `connectedk8s` and `k8s-extension` whl packages and changing the `connectedk8s` and `k8s-extension` values to match the (Major.Minor.Patch) version format shown above_ + +### Step 6: Run the Bootstrap Command +To bootstrap the environment with AKS and Arc clusters, run +```powershell +.\Bootstrap.ps1 +``` +This script will provision the AKS and Arc clusters needed to run the integration test suite + +## Testing + +### Testing All Extension Suites +To test all extension test suites, you must call `.\Test.ps1` with the `-ExtensionType` parameter set to either `Public` or `Private`. Based on this flag, the test suite will install the extension type specified below + +| `-ExtensionType` | Installs `az extension` | +| ---------------- | --------------------- | +| `Public` | `k8s-extension` | +| `Private` | `k8s-extension-private` | + +For example, when calling +```bash +.\Test.ps1 -ExtensionType Public +``` +the script will install your `k8s-extension` whl package and run the full test suite of `*.Tests.ps1` files included in the `\test\extensions` directory + +### Testing Public Extensions Only +If you only want to run the test cases against public-preview or GA extension test cases, you can use the `-OnlyPublicTests` flag to specify this +```bash +.\Test.ps1 -ExtensionType Public -OnlyPublicTests +``` + +### Testing Specific Extension Suite + +If you only want to run the test script on your specific test file, you can do so by specifying path to your extension test suite in the execution call + +```powershell +.\Test.ps1 -Path +``` +For example to call the `AzureMonitor.Tests.ps1` test suite, we run +```powershell +.\Test.ps1 -ExtensionType Public -Path .\test\extensions\public\AzureMonitor.Tests.ps1 +``` + +### Skipping Extension Re-Install + +By default the `Test.ps1` script will uninstall any old versions of `k8s-extension`/'`k8s-extension-private` and re-install the version specified in `settings.json`. If you do not want this re-installation to occur, you can specify the `-SkipInstall` flag to skip this process. + +```powershell +.\Test.ps1 -ExtensionType Public -SkipInstall +``` + +## Cleanup +To cleanup the AKS and Arc clusters you have provisioned in testing, run +```powershell +.\Cleanup.ps1 +``` +This will remove the AKS and Arc clusters as well as the `\tmp` directory that were created by the bootstrapping script. \ No newline at end of file diff --git a/testing/Test.ps1 b/testing/Test.ps1 new file mode 100644 index 00000000000..7c6f522d082 --- /dev/null +++ b/testing/Test.ps1 @@ -0,0 +1,99 @@ +param ( + [string] $Path, + [switch] $SkipInstall, + [switch] $CI, + [switch] $ParallelCI, + [switch] $OnlyPublicTests, + + [Parameter(Mandatory=$True)] + [ValidateSet('connectedk8s')] + [string]$Type +) + +# Disable confirm prompt for script +# Only show errors, don't show warnings +az config set core.disable_confirm_prompt=true +az config set core.only_show_errors=true + +$ENVCONFIG = Get-Content -Path $PSScriptRoot/settings.json | ConvertFrom-Json + +# Install the powershell-yaml module +# Needed to parse the kubeconfig file +Install-Module -Name powershell-yaml -Force -Scope CurrentUser + +az account set --subscription $ENVCONFIG.subscriptionId + +$Env:KUBECONFIG="$PSScriptRoot/tmp/KUBECONFIG" +$TestFileDirectory="$PSScriptRoot/results" + +if (-not (Test-Path -Path $TestFileDirectory)) { + New-Item -ItemType Directory -Path $TestFileDirectory +} + +if ($Type -eq 'connectedk8s') { + $connectedk8sVersion = $ENVCONFIG.extensionVersion.'connectedk8s' + if (!$SkipInstall) { + Write-Host "Removing the old connectedk8s extension..." + az extension remove -n connectedk8s + Write-Host "Installing connectedk8s version $connectedk8sVersion..." + az extension add --source ./bin/connectedk8s-$connectedk8sVersion-py2.py3-none-any.whl + } + $testFilePaths = "$PSScriptRoot/test/configurations" +} + +if ($ParallelCI) { + # This runs the tests in parallel during the CI pipline to speed up testing + + Write-Host "Invoking Pester to run tests from '$testFilePath'..." + $testFiles = @() + foreach ($paths in $testFilePaths) + { + $temp = Get-ChildItem $paths + $testFiles += $temp + } + $resultFileNumber = 0 + foreach ($testFile in $testFiles) + { + $resultFileNumber++ + $testName = Split-Path $testFile –leaf + Start-Job -ArgumentList $testName, $testFile, $resultFileNumber, $TestFileDirectory -Name $testName -ScriptBlock { + param($name, $testFile, $resultFileNumber, $testFileDirectory) + + Write-Host "$testFile to result file #$resultFileNumber" + $testResult = Invoke-Pester $testFile -Passthru -Output Detailed + $testResult | Export-JUnitReport -Path "$testFileDirectory/$name.xml" + } + } + + do { + Write-Host ">> Still running tests @ $(Get-Date –Format "HH:mm:ss")" –ForegroundColor Blue + Get-Job | Where-Object { $_.State -eq "Running" } | Format-Table –AutoSize + Start-Sleep –Seconds 30 + } while((Get-Job | Where-Object { $_.State -eq "Running" } | Measure-Object).Count -ge 1) + + Get-Job | Wait-Job + $failedJobs = Get-Job | Where-Object { -not ($_.State -eq "Completed")} + Get-Job | Receive-Job –AutoRemoveJob –Wait –ErrorAction 'Continue' + + if ($failedJobs.Count -gt 0) { + Write-Host "Failed Jobs" –ForegroundColor Red + $failedJobs + throw "One or more tests failed" + } +} elseif ($CI) { + if ($Path) { + $testFilePath = "$PSScriptRoot/$Path" + } + Write-Host "Invoking Pester to run tests from '$testFilePath'..." + $testResult = Invoke-Pester $testFilePath -Passthru -Output Detailed + $testName = Split-Path $testFilePath –leaf + $testResult | Export-JUnitReport -Path "$testFileDirectory/$testName.xml" +} else { + if ($Path) { + Write-Host "Invoking Pester to run tests from '$PSScriptRoot/$Path'" + Invoke-Pester -Output Detailed $PSScriptRoot/$Path + } else { + Write-Host "Invoking Pester to run tests from '$testFilePath'..." + Invoke-Pester -Output Detailed $testFilePath + } +} \ No newline at end of file diff --git a/testing/bin/connectedk8s-1.0.0-py3-none-any.whl b/testing/bin/connectedk8s-1.0.0-py3-none-any.whl new file mode 100644 index 00000000000..08f34250036 Binary files /dev/null and b/testing/bin/connectedk8s-1.0.0-py3-none-any.whl differ diff --git a/testing/bin/connectedk8s-values.yaml b/testing/bin/connectedk8s-values.yaml new file mode 100644 index 00000000000..35716eb9ba1 --- /dev/null +++ b/testing/bin/connectedk8s-values.yaml @@ -0,0 +1,3 @@ +systemDefaultValues: + extensionoperator: + enabled: true \ No newline at end of file diff --git a/testing/bin/k8s_configuration-1.0.0-py3-none-any.whl b/testing/bin/k8s_configuration-1.0.0-py3-none-any.whl new file mode 100644 index 00000000000..cc8e8e0995f Binary files /dev/null and b/testing/bin/k8s_configuration-1.0.0-py3-none-any.whl differ diff --git a/testing/bin/k8s_extension-0.3.0-py3-none-any.whl b/testing/bin/k8s_extension-0.3.0-py3-none-any.whl new file mode 100644 index 00000000000..feb28b80b43 Binary files /dev/null and b/testing/bin/k8s_extension-0.3.0-py3-none-any.whl differ diff --git a/testing/owners.txt b/testing/owners.txt new file mode 100644 index 00000000000..c1bbe9a9e5c --- /dev/null +++ b/testing/owners.txt @@ -0,0 +1,2 @@ +joinnis +nanthi \ No newline at end of file diff --git a/testing/pipeline/k8s-custom-pipelines.yml b/testing/pipeline/k8s-custom-pipelines.yml new file mode 100644 index 00000000000..2cfa227661d --- /dev/null +++ b/testing/pipeline/k8s-custom-pipelines.yml @@ -0,0 +1,381 @@ +resources: +- repo: self + +trigger: + batch: true + branches: + include: + - 'main' + +pr: + branches: + include: + - '*' + +stages: +- stage: BuildTestPublishExtension + displayName: "Build, Test, and Publish Extension" + variables: + TEST_PATH: $(Agent.BuildDirectory)/s/testing + CLI_REPO_PATH: $(Agent.BuildDirectory)/s + EXTENSION_NAME: "connectedk8s" + EXTENSION_FILE_NAME: "connectedk8s" + SUBSCRIPTION_ID: "15c06b1b-01d6-407b-bb21-740b8617dea3" + RESOURCE_GROUP: "K8sPartnerExtensionTest" + BASE_CLUSTER_NAME: "connectedk8s-cluster" + jobs: + - template: ./templates/run-test.yml + parameters: + jobName: BasicOnboardingTest + path: ./test/configurations/BasicOnboarding.Tests.ps1 + - template: ./templates/run-test.yml + parameters: + jobName: EnableDisableFeaturesTest + path: ./test/configurations/EnableDisableFeatures.Tests.ps1 + - template: ./templates/run-test.yml + parameters: + jobName: AutoUpdateTest + path: ./test/configurations/AutoUpdate.Tests.ps1 + - template: ./templates/run-test.yml + parameters: + jobName: ProxyTest + path: ./test/configurations/Proxy.Tests.ps1 + - template: ./templates/run-test.yml + parameters: + jobName: GatewayTest + path: ./test/configurations/Gateway.Tests.ps1 + - template: ./templates/run-test.yml + parameters: + jobName: WorkloadIdentityTest + path: ./test/configurations/WorkloadIdentity.Tests.ps1 + - template: ./templates/run-test.yml + parameters: + jobName: TroubleshootTest + path: ./test/configurations/Troubleshoot.Tests.ps1 + - template: ./templates/run-test.yml + parameters: + jobName: Connectedk8sProxyTest + path: ./test/configurations/ConnectProxy.Tests.ps1 + - template: ./templates/run-test.yml + parameters: + jobName: ForcedDeleteTest + path: ./test/configurations/ForcedDelete.Tests.ps1 + - job: BuildPublishExtension + pool: + vmImage: 'ubuntu-latest' + displayName: "Build and Publish the Extension Artifact" + variables: + CLI_REPO_PATH: $(Agent.BuildDirectory)/s + EXTENSION_NAME: "connectedk8s" + steps: + - task: UsePythonVersion@0 + displayName: 'Use Python 3.13' + inputs: + versionSpec: 3.13 + - bash: | + set -ev + echo "Building extension ${EXTENSION_NAME}..." + + # prepare and activate virtualenv + pip install virtualenv + python3 -m venv env/ + source env/bin/activate + + # clone azure-cli + pip install --upgrade pip + pip install azdev + + ls $(CLI_REPO_PATH) + + azdev --version + azdev setup -r $(CLI_REPO_PATH) -e $(EXTENSION_NAME) + azdev extension build $(EXTENSION_NAME) + workingDirectory: $(CLI_REPO_PATH) + displayName: "Setup and Build Extension with azdev" + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: $(CLI_REPO_PATH)/dist + +- stage: AzureCLIOfficial + displayName: "Azure Official CLI Code Checks" + dependsOn: [] + jobs: + - job: CheckLicenseHeader + displayName: "Check License" + pool: + vmImage: 'ubuntu-latest' + steps: + - task: UsePythonVersion@0 + displayName: 'Use Python 3.10' + inputs: + versionSpec: 3.10 + - bash: | + set -ev + + # prepare and activate virtualenv + python -m venv env/ + + chmod +x ./env/bin/activate + source ./env/bin/activate + + # clone azure-cli + git clone -q --single-branch -b dev https://github.com/Azure/azure-cli.git ../azure-cli + + pip install --upgrade pip + pip install -q azdev + + azdev setup -c ../azure-cli -r ./ + + azdev --version + az --version + + azdev verify license + + - job: IndexVerify + displayName: "Verify Extensions Index" + pool: + vmImage: 'ubuntu-latest' + steps: + - task: UsePythonVersion@0 + displayName: 'Use Python 3.10' + inputs: + versionSpec: 3.10 + - bash: | + #!/usr/bin/env bash + set -ev + pip install wheel==0.30.0 requests packaging + export CI="ADO" + python ./scripts/ci/test_index.py -v + displayName: "Verify Extensions Index" + + - job: UnitTests + displayName: "Unit Tests" + pool: + vmImage: 'ubuntu-latest' + steps: + - task: UsePythonVersion@0 + displayName: 'Use Python 3.12' + inputs: + versionSpec: '3.12' + - bash: pip install wheel==0.30.0 + displayName: 'Install wheel==0.30.0' + - bash: | + set -ev + + # prepare and activate virtualenv + pip install virtualenv + python -m virtualenv venv/ + source ./venv/bin/activate + + # clone azure-cli + git clone --single-branch -b dev https://github.com/Azure/azure-cli.git ../azure-cli + + pip install --upgrade pip + pip install azdev + + azdev --version + + azdev setup -c ../azure-cli -r ./ -e connectedk8s + current_dir=$(pwd) + echo "Current directory: $current_dir" + pip install pytest + cd /home/vsts/work/1/s/src/connectedk8s/azext_connectedk8s/tests/unittests + pytest --junitxml=test-results.xml + displayName: 'Run UnitTests test' + - task: PublishTestResults@2 + inputs: + testResultsFormat: 'JUnit' + testResultsFiles: '**/test-results.xml' + failTaskOnFailedTests: true + - job: SourceTests + displayName: "Integration Tests, Build Tests" + pool: + vmImage: 'ubuntu-latest' + strategy: + matrix: + Python39: + python.version: '3.9' + Python310: + python.version: '3.10' + Python311: + python.version: '3.11' + Python312: + python.version: '3.12' + steps: + - task: UsePythonVersion@0 + displayName: 'Use Python $(python.version)' + inputs: + versionSpec: '$(python.version)' + - bash: pip install wheel==0.30.0 + displayName: 'Install wheel==0.30.0' + - bash: | + set -ev + + # prepare and activate virtualenv + pip install virtualenv + python -m virtualenv venv/ + source ./venv/bin/activate + + # clone azure-cli + git clone --single-branch -b dev https://github.com/Azure/azure-cli.git ../azure-cli + + pip install --upgrade pip + pip install azdev + + azdev --version + + azdev setup -c ../azure-cli -r ./ -e connectedk8s + azdev test connectedk8s + displayName: 'Run integration test and build test' + + - job: AzdevLinterModifiedExtensions + displayName: "azdev linter on Modified Extensions" + pool: + vmImage: 'ubuntu-latest' + steps: + - task: UsePythonVersion@0 + displayName: 'Use Python 3.12' + inputs: + versionSpec: 3.12 + - bash: | + set -ev + + # prepare and activate virtualenv + pip install virtualenv + python -m virtualenv venv/ + source ./venv/bin/activate + + # clone azure-cli + git clone --single-branch -b dev https://github.com/Azure/azure-cli.git ../azure-cli + + pip install --upgrade pip + pip install azdev + + azdev --version + + azdev setup -c ../azure-cli -r ./ -e connectedk8s + # Installing setuptools with a version higher than 70.0.0 will not generate metadata.json + pip install setuptools==70.0.0 + pip list -v + + # overwrite the default AZURE_EXTENSION_DIR set by ADO + AZURE_EXTENSION_DIR=~/.azure/cliextensions az --version + + AZURE_EXTENSION_DIR=~/.azure/cliextensions azdev linter --include-whl-extensions connectedk8s + displayName: "CLI Linter on Modified Extension" + env: + ADO_PULL_REQUEST_LATEST_COMMIT: $(System.PullRequest.SourceCommitId) + ADO_PULL_REQUEST_TARGET_BRANCH: $(System.PullRequest.TargetBranch) + + - job: AzdevStyleModifiedExtensions + displayName: "azdev style on Modified Extensions" + continueOnError: true + pool: + vmImage: 'ubuntu-latest' + steps: + - task: UsePythonVersion@0 + displayName: 'Use Python 3.12' + inputs: + versionSpec: 3.12 + - bash: | + set -ev + + # prepare and activate virtualenv + python -m venv env + chmod +x env/bin/activate + source ./env/bin/activate + + # clone azure-cli + git clone -q --single-branch -b dev https://github.com/Azure/azure-cli.git ../azure-cli + + pip install --upgrade pip + pip install azdev + + azdev --version + + azdev setup -c ../azure-cli -r ./ -e connectedk8s + # Installing setuptools with a version higher than 70.0.0 will not generate metadata.json + pip install setuptools==70.0.0 + pip list -v + az --version + + # overwrite the default AZURE_EXTENSION_DIR set by ADO + AZURE_EXTENSION_DIR=~/.azure/cliextensions az --version + + AZURE_EXTENSION_DIR=~/.azure/cliextensions azdev style connectedk8s + displayName: "azdev style on Modified Extensions" + env: + ADO_PULL_REQUEST_LATEST_COMMIT: $(System.PullRequest.SourceCommitId) + ADO_PULL_REQUEST_TARGET_BRANCH: $(System.PullRequest.TargetBranch) + + - job: RuffCheck + displayName: "Lint connectedk8s with ruff check" + pool: + vmImage: 'ubuntu-latest' + steps: + - task: UsePythonVersion@0 + displayName: 'Use Python 3.12' + inputs: + versionSpec: 3.12 + - bash: | + set -ev + + # prepare and activate virtualenv + cd src/connectedk8s + python -m venv env + source ./env/bin/activate + + pip install --upgrade pip + pip install azure-cli --editable .[linting] + + ruff check + + displayName: "ruff check" + + - job: RuffFormat + displayName: "Check connected8ks formatting with ruff" + pool: + vmImage: 'ubuntu-latest' + steps: + - task: UsePythonVersion@0 + displayName: 'Use Python 3.12' + inputs: + versionSpec: 3.12 + - bash: | + set -ev + + # prepare and activate virtualenv + cd src/connectedk8s + python -m venv env + source ./env/bin/activate + + pip install --upgrade pip + pip install azure-cli --editable .[linting] + + ruff format --check + + displayName: "ruff format check" + + - job: TypeChecking + displayName: "Typecheck connected8ks with mypy" + pool: + vmImage: 'ubuntu-latest' + steps: + - task: UsePythonVersion@0 + displayName: 'Use Python 3.12' + inputs: + versionSpec: 3.12 + - bash: | + set -ev + + # prepare and activate virtualenv + cd src/connectedk8s + python -m venv env + source ./env/bin/activate + + pip install --upgrade pip + pip install azure-cli --editable .[linting] + + mypy + + displayName: "mypy" diff --git a/testing/pipeline/templates/run-test.yml b/testing/pipeline/templates/run-test.yml new file mode 100644 index 00000000000..cd2679160a3 --- /dev/null +++ b/testing/pipeline/templates/run-test.yml @@ -0,0 +1,112 @@ +parameters: + jobName: '' + path: '' + +jobs: +- job: ${{ parameters.jobName}} + pool: + vmImage: 'ubuntu-latest' + steps: + - bash: | + echo "Installing helm3" + curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 + chmod 700 get_helm.sh + ./get_helm.sh --version v3.6.3 + echo "Installing kubectl" + curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl" + chmod +x ./kubectl + sudo mv ./kubectl /usr/local/bin/kubectl + kubectl version --client + displayName: "Setup the VM with helm3 and kubectl" + + - task: UsePythonVersion@0 + displayName: 'Use Python 3.13' + inputs: + versionSpec: 3.13 + + - bash: | + set -ev + echo "Building extension ${EXTENSION_NAME}..." + # prepare and activate virtualenv + pip install virtualenv + python3 -m venv env/ + source env/bin/activate + # clone azure-cli + git clone -q --single-branch -b dev https://github.com/Azure/azure-cli.git ../azure-cli + pip install --upgrade pip + pip install -q azdev + ls $(CLI_REPO_PATH) + azdev --version + azdev setup -c ../azure-cli -r $(CLI_REPO_PATH) -e $(EXTENSION_NAME) + azdev extension build $(EXTENSION_NAME) + workingDirectory: $(CLI_REPO_PATH) + displayName: "Setup and Build Extension with azdev" + + - bash: | + K8S_CONFIG_VERSION=$(ls ${EXTENSION_FILE_NAME}* | cut -d "-" -f2) + echo "##vso[task.setvariable variable=K8S_CONFIG_VERSION]$K8S_CONFIG_VERSION" + cp * $(TEST_PATH)/bin + workingDirectory: $(CLI_REPO_PATH)/dist + displayName: "Copy the Built .whl to Extension Test Path" + + - bash: | + RAND_STR=$RANDOM + AKS_CLUSTER_NAME="${BASE_CLUSTER_NAME}-${RAND_STR}-aks" + ARC_CLUSTER_NAME="${BASE_CLUSTER_NAME}-${RAND_STR}-arc" + + JSON_STRING=$(jq -n \ + --arg SUB_ID "$SUBSCRIPTION_ID" \ + --arg RG "$RESOURCE_GROUP" \ + --arg AKS_CLUSTER_NAME "$AKS_CLUSTER_NAME" \ + --arg ARC_CLUSTER_NAME "$ARC_CLUSTER_NAME" \ + --arg K8S_CONFIG_VERSION "$K8S_CONFIG_VERSION" \ + '{subscriptionId: $SUB_ID, resourceGroup: $RG, aksClusterName: $AKS_CLUSTER_NAME, arcClusterName: $ARC_CLUSTER_NAME, extensionVersion: {"connectedk8s": $K8S_CONFIG_VERSION}, customLocationsOid: "51dfe1e8-70c6-4de5-a08e-e18aff23d815"}') + echo $JSON_STRING > settings.json + cat settings.json + workingDirectory: $(TEST_PATH) + displayName: "Generate a settings.json file" + + - bash : | + echo "Downloading the kind script" + # Get the latest version tag and download + LATEST_KIND_VERSION=$(curl -s https://api.github.com/repos/kubernetes-sigs/kind/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + curl -Lo ./kind "https://kind.sigs.k8s.io/dl/${LATEST_KIND_VERSION}/kind-linux-amd64" + chmod +x ./kind + ./kind create cluster + displayName: "Create and Start the Kind cluster" + - bash: | + curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash + displayName: "Upgrade az to latest version" + + - bash: | + curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 + chmod 700 get_helm.sh + ./get_helm.sh --version v3.6.3 + displayName: "Install Helm" + + - task: AzureCLI@2 + displayName: Bootstrap + inputs: + azureSubscription: AzureResourceConnection + scriptType: pscore + scriptLocation: inlineScript + inlineScript: | + .\Bootstrap.ps1 -CI + workingDirectory: $(TEST_PATH) + - task: AzureCLI@2 + displayName: Run the Test Suite for ${{ parameters.path }} + inputs: + azureSubscription: AzureResourceConnection + scriptType: pscore + scriptLocation: inlineScript + inlineScript: | + .\Test.ps1 -CI -Path ${{ parameters.path }} -Type connectedk8s + workingDirectory: $(TEST_PATH) + continueOnError: true + + - task: PublishTestResults@2 + inputs: + testResultsFormat: 'JUnit' + testResultsFiles: '**/testing/results/*.xml' + failTaskOnFailedTests: true + condition: succeededOrFailed() diff --git a/testing/settings.template.json b/testing/settings.template.json new file mode 100644 index 00000000000..657126c20aa --- /dev/null +++ b/testing/settings.template.json @@ -0,0 +1,12 @@ +{ + "subscriptionId": "", + "resourceGroup": "", + "aksClusterName": "", + "arcClusterName": "", + + "extensionVersion": { + "k8s-extension": "0.3.0", + "k8s-extension-private": "0.1.0", + "connectedk8s": "1.0.0" + } +} \ No newline at end of file diff --git a/testing/test/configurations/AutoUpdate.Tests.ps1 b/testing/test/configurations/AutoUpdate.Tests.ps1 new file mode 100644 index 00000000000..d55029ceeb8 --- /dev/null +++ b/testing/test/configurations/AutoUpdate.Tests.ps1 @@ -0,0 +1,62 @@ +Describe 'Auto Upgrade Scenario' { + BeforeAll { + . $PSScriptRoot/../helper/Constants.ps1 + } + + It 'Check if basic onboarding works with auto-upgrade disabled' { + az connectedk8s connect -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup -l $ARC_LOCATION --disable-auto-upgrade --no-wait + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $jsonOutput = [System.Text.Json.JsonDocument]::Parse($output) + $provisioningState = ($output | ConvertFrom-Json).provisioningState + $autoUpdate = $jsonOutput.RootElement.GetProperty("arcAgentProfile").GetProperty("agentAutoUpgrade").GetString() + Write-Host "Provisioning State: $provisioningState" + Write-Host "Auto Update: $autoUpdate" + if ($provisioningState -eq $SUCCEEDED -and $autoUpdate -eq "Disabled") { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It 'Enable auto-upgrade using update cmd' { + az connectedk8s update -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --auto-upgrade true + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $jsonOutput = [System.Text.Json.JsonDocument]::Parse($output) + $provisioningState = ($output | ConvertFrom-Json).provisioningState + $autoUpdate = $jsonOutput.RootElement.GetProperty("arcAgentProfile").GetProperty("agentAutoUpgrade").GetString() + Write-Host "Provisioning State: $provisioningState" + Write-Host "Auto Update: $autoUpdate" + if ($provisioningState -eq $SUCCEEDED -and $autoUpdate -eq "Enabled") { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It "Delete the connected instance" { + az connectedk8s delete -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --force -y + $? | Should -BeTrue + + # Configuration should be removed from the resource model + az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $? | Should -BeFalse + } +} \ No newline at end of file diff --git a/testing/test/configurations/BasicOnboarding.Tests.ps1 b/testing/test/configurations/BasicOnboarding.Tests.ps1 new file mode 100644 index 00000000000..8d5975dae67 --- /dev/null +++ b/testing/test/configurations/BasicOnboarding.Tests.ps1 @@ -0,0 +1,62 @@ +Describe 'Basic Onboarding Scenario' { + BeforeAll { + . $PSScriptRoot/../helper/Constants.ps1 + } + + It 'Check if basic onboarding works correctly' { + az connectedk8s connect -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup -l $ARC_LOCATION --no-wait + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $jsonOutput = [System.Text.Json.JsonDocument]::Parse($output) + $provisioningState = ($output | ConvertFrom-Json).provisioningState + $autoUpdate = $jsonOutput.RootElement.GetProperty("arcAgentProfile").GetProperty("agentAutoUpgrade").GetString() + Write-Host "Provisioning State: $provisioningState" + Write-Host "Auto Update: $autoUpdate" + if ($provisioningState -eq $SUCCEEDED -and $autoUpdate -eq "Enabled") { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It 'Disable auto-upgrade' { + az connectedk8s update -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --auto-upgrade false + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $jsonOutput = [System.Text.Json.JsonDocument]::Parse($output) + $provisioningState = ($output | ConvertFrom-Json).provisioningState + $autoUpdate = $jsonOutput.RootElement.GetProperty("arcAgentProfile").GetProperty("agentAutoUpgrade").GetString() + Write-Host "Provisioning State: $provisioningState" + Write-Host "Auto Update: $autoUpdate" + if ($provisioningState -eq $SUCCEEDED -and $autoUpdate -eq "Disabled") { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It "Delete the connected instance" { + az connectedk8s delete -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup -y + $? | Should -BeTrue + + # Configuration should be removed from the resource model + az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $? | Should -BeFalse + } +} \ No newline at end of file diff --git a/testing/test/configurations/ConnectProxy.Tests.ps1 b/testing/test/configurations/ConnectProxy.Tests.ps1 new file mode 100644 index 00000000000..4de00bbeba0 --- /dev/null +++ b/testing/test/configurations/ConnectProxy.Tests.ps1 @@ -0,0 +1,98 @@ +Describe 'Connectedk8s Proxy Scenario' { + BeforeAll { + . $PSScriptRoot/../helper/Constants.ps1 + } + + It 'Check if basic onboarding works correctly' { + az connectedk8s connect -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup -l $ARC_LOCATION --no-wait + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $provisioningState = ($output | ConvertFrom-Json).provisioningState + Write-Host "Provisioning State: $provisioningState" + if ($provisioningState -eq $SUCCEEDED) { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It 'Connectedk8s proxy test with non-empty kubeconfig' { + # Start the proxy command as a background job + $proxyJob = Start-Job -ScriptBlock { + param($ClusterName, $ResourceGroup) + + # Capture output and errors + try { + $output = az connectedk8s proxy -n $ClusterName -g $ResourceGroup 2>&1 + return @{ Success = $LASTEXITCODE -eq 0; Output = $output } + } catch { + return @{ Success = $false; Output = $_.Exception.Message } + } + } -ArgumentList $ENVCONFIG.arcClusterName, $ENVCONFIG.resourceGroup + + # Wait for a certain amount of time (e.g., 30 seconds) + Start-Sleep -Seconds 60 + + # Display the output + Write-Host "Proxy Job State: $($proxyJob.State)" + + # Check if the job ran successfully + $proxyJob.State | Should -Be 'Running' + + # Check if the kubeconfig file has been updated to use the proxy + $kubeconfigPath = "~/.kube/config" + $kubeconfig = Get-Content $kubeconfigPath -Raw | ConvertFrom-Yaml + # Extract the current context + $currentContext = $kubeconfig.'current-context' + + # Validate that the current context is for the arc machine + $currentContext | Should -Be $ENVCONFIG.arcClusterName + + # Find the cluster associated with the current context + $context = $kubeconfig.contexts | Where-Object { $_.name -eq $currentContext } + $clusterName = $context.context.cluster + + # Retrieve the server URL for the cluster + $cluster = $kubeconfig.clusters | Where-Object { $_.name -eq $clusterName } + $server = $cluster.cluster.server + + # Validate the server URL + $server | Should -Match "^https://127.0.0.1:47011/proxies/" + + # Check if the proxy command ran successfully + $kubectlJob = Start-Job -ScriptBlock { + try { + $output = kubectl get pods -n azure-arc 2>&1 + return @{ Success = $LASTEXITCODE -eq 0; Output = $output } + } catch { + return @{ Success = $false; Output = $_.Exception.Message } + } + } + + $kubectlJob | Wait-Job + $kubectlResult = Receive-Job -Job $kubectlJob + + # Assert that the result is 0 + $kubectlResult.Success | Should -BeTrue + + Stop-Job -Job $proxyJob + Remove-Job -Job $proxyJob + } + + It "Delete the connected instance" { + az connectedk8s delete -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --force -y + $? | Should -BeTrue + + # Configuration should be removed from the resource model + az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $? | Should -BeFalse + } +} \ No newline at end of file diff --git a/testing/test/configurations/EnableDisableFeatures.Tests.ps1 b/testing/test/configurations/EnableDisableFeatures.Tests.ps1 new file mode 100644 index 00000000000..8c6f1f5d1f3 --- /dev/null +++ b/testing/test/configurations/EnableDisableFeatures.Tests.ps1 @@ -0,0 +1,111 @@ +Describe 'ConnectedK8s Enable Disable Features Scenario' { + BeforeAll { + . $PSScriptRoot/../helper/Constants.ps1 + + function Invoke-AzCommand { + param ( + [string]$Command + ) + Write-Host "Executing: $Command" -ForegroundColor Yellow + $result = Invoke-Expression $Command + return $result + } + + function Wait-ForProvisioning { + param ( + [string]$expectedProvisioningState, + [string]$expectedAutoUpdate + ) + $n = 0 + do { + $output = Invoke-AzCommand "az connectedk8s show -n $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup)" + $jsonOutput = [System.Text.Json.JsonDocument]::Parse($output) + $provisioningState = ($output | ConvertFrom-Json).provisioningState + $autoUpdate = $jsonOutput.RootElement.GetProperty("arcAgentProfile").GetProperty("agentAutoUpgrade").GetString() + Write-Host "Provisioning State: $provisioningState" + Write-Host "Auto Update: $autoUpdate" + if ($provisioningState -eq $expectedProvisioningState -and $autoUpdate -eq $expectedAutoUpdate) { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + } + + It 'Onboard Connected cluster with no features enabled' { + Invoke-AzCommand "az connectedk8s connect -n $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) -l $ARC_LOCATION --no-wait" + $? | Should -BeTrue + Start-Sleep -Seconds 10 + Wait-ForProvisioning -expectedProvisioningState $SUCCEEDED -expectedAutoUpdate "Enabled" + } + + It 'Enable azure-rbac feature' { + Invoke-AzCommand "az connectedk8s enable-features -n $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --features azure-rbac" + $? | Should -BeTrue + Start-Sleep -Seconds 10 + Wait-ForProvisioning -expectedProvisioningState $SUCCEEDED -expectedAutoUpdate "Enabled" + } + + It 'Disable azure-rbac feature' { + Invoke-AzCommand "az connectedk8s disable-features -n $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --features azure-rbac --yes" + $? | Should -BeTrue + Start-Sleep -Seconds 10 + Wait-ForProvisioning -expectedProvisioningState $SUCCEEDED -expectedAutoUpdate "Enabled" + } + + It 'Enable cluster-connect feature' { + Invoke-AzCommand "az connectedk8s enable-features -n $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --features cluster-connect" + $? | Should -BeTrue + Start-Sleep -Seconds 10 + Wait-ForProvisioning -expectedProvisioningState $SUCCEEDED -expectedAutoUpdate "Enabled" + } + + It 'Disable cluster-connect feature' { + Invoke-AzCommand "az connectedk8s disable-features -n $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --features cluster-connect --yes" + $? | Should -BeTrue + Start-Sleep -Seconds 10 + Wait-ForProvisioning -expectedProvisioningState $SUCCEEDED -expectedAutoUpdate "Enabled" + } + + It 'Enable custom-locations feature' { + Invoke-AzCommand "az connectedk8s enable-features -n $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --features custom-locations --custom-locations-oid $($ENVCONFIG.customLocationsOid)" + $? | Should -BeTrue + Start-Sleep -Seconds 10 + Wait-ForProvisioning -expectedProvisioningState $SUCCEEDED -expectedAutoUpdate "Enabled" + } + + It 'Disable custom-locations feature' { + Invoke-AzCommand "az connectedk8s disable-features -n $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --features custom-locations --yes" + $? | Should -BeTrue + Start-Sleep -Seconds 10 + Wait-ForProvisioning -expectedProvisioningState $SUCCEEDED -expectedAutoUpdate "Enabled" + } + + It 'Enable all features (cluster-connect, custom-locations, azure-rbac) together' { + Invoke-AzCommand "az connectedk8s enable-features -n $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --features cluster-connect custom-locations azure-rbac --custom-locations-oid $($ENVCONFIG.customLocationsOid)" + $? | Should -BeTrue + Start-Sleep -Seconds 10 + Wait-ForProvisioning -expectedProvisioningState $SUCCEEDED -expectedAutoUpdate "Enabled" + } + + It 'Disable all features (cluster-connect, custom-locations, azure-rbac) together' { + Invoke-AzCommand "az connectedk8s disable-features -n $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) --features cluster-connect custom-locations azure-rbac --yes" + $? | Should -BeTrue + Start-Sleep -Seconds 10 + Wait-ForProvisioning -expectedProvisioningState $SUCCEEDED -expectedAutoUpdate "Enabled" + } + + It "Delete the connected instance" { + Invoke-AzCommand "az connectedk8s delete -n $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup) -y" + $? | Should -BeTrue + + # Wait for deletion to propagate through the resource model + Start-Sleep -Seconds 30 + + # Configuration should be removed from the resource model - expect ResourceNotFound error + $output = Invoke-AzCommand "az connectedk8s show -n $($ENVCONFIG.arcClusterName) -g $($ENVCONFIG.resourceGroup)" 2>&1 + $output | Should -Match "(ResourceNotFound|could not be found|not found)" + } +} \ No newline at end of file diff --git a/testing/test/configurations/ForcedDelete.Tests.ps1 b/testing/test/configurations/ForcedDelete.Tests.ps1 new file mode 100644 index 00000000000..ca38873dd54 --- /dev/null +++ b/testing/test/configurations/ForcedDelete.Tests.ps1 @@ -0,0 +1,38 @@ +Describe 'Basic Onboarding with Force delete Scenario' { + BeforeAll { + . $PSScriptRoot/../helper/Constants.ps1 + } + + It 'Check if onboarding works correctly' { + az connectedk8s connect -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup -l $ARC_LOCATION --no-wait + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $jsonOutput = [System.Text.Json.JsonDocument]::Parse($output) + $provisioningState = ($output | ConvertFrom-Json).provisioningState + $autoUpdate = $jsonOutput.RootElement.GetProperty("arcAgentProfile").GetProperty("agentAutoUpgrade").GetString() + Write-Host "Provisioning State: $provisioningState" + Write-Host "Auto Update: $autoUpdate" + if ($provisioningState -eq $SUCCEEDED -and $autoUpdate -eq "Enabled") { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It "Force delete the connected instance" { + az connectedk8s delete -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --force -y + $? | Should -BeTrue + + # Configuration should be removed from the resource model + az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $? | Should -BeFalse + } +} \ No newline at end of file diff --git a/testing/test/configurations/Gateway.Tests.ps1 b/testing/test/configurations/Gateway.Tests.ps1 new file mode 100644 index 00000000000..9948e326d09 --- /dev/null +++ b/testing/test/configurations/Gateway.Tests.ps1 @@ -0,0 +1,112 @@ +Describe 'Onboarding with Gateway Scenario' { + BeforeAll { + . $PSScriptRoot/../helper/Constants.ps1 + + $gatewayResourceId = "/subscriptions/15c06b1b-01d6-407b-bb21-740b8617dea3/resourceGroups/connectedk8sCLITestResources/providers/Microsoft.HybridCompute/gateways/gateway-test-cli" + } + + It 'Check if onboarding works with gateway enabled' { + az connectedk8s connect -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup -l $ARC_LOCATION --gateway-resource-id $gatewayResourceId + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $jsonOutput = [System.Text.Json.JsonDocument]::Parse($output) + $provisioningState = ($output | ConvertFrom-Json).provisioningState + $gatewayStatus = $jsonOutput.RootElement.GetProperty("gateway").GetProperty("enabled").GetBoolean() + Write-Host "Provisioning State: $provisioningState" + Write-Host "Gateway Status: $gatewayStatus" + if ($provisioningState -eq $SUCCEEDED -and $gatewayStatus -eq $true) { + break + } + Start-Sleep -Seconds 30 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It 'Disable the gateway' { + az connectedk8s update -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --disable-gateway + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $jsonOutput = [System.Text.Json.JsonDocument]::Parse($output) + $provisioningState = ($output | ConvertFrom-Json).provisioningState + $gatewayStatus = $jsonOutput.RootElement.GetProperty("gateway").GetProperty("enabled").GetBoolean() + Write-Host "Provisioning State: $provisioningState" + Write-Host "Gateway Status: $gatewayStatus" + if ($provisioningState -eq $SUCCEEDED -and $gatewayStatus -eq $false) { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It 'Update the cluster to use gateway again using update cmd' { + az connectedk8s update -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --gateway-resource-id $gatewayResourceId + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $jsonOutput = [System.Text.Json.JsonDocument]::Parse($output) + $provisioningState = ($output | ConvertFrom-Json).provisioningState + $gatewayStatus = $jsonOutput.RootElement.GetProperty("gateway").GetProperty("enabled").GetBoolean() + Write-Host "Provisioning State: $provisioningState" + Write-Host "Gateway Status: $gatewayStatus" + if ($provisioningState -eq $SUCCEEDED -and $gatewayStatus -eq $true) { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It 'Disable the gateway' { + az connectedk8s update -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --disable-gateway + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $jsonOutput = [System.Text.Json.JsonDocument]::Parse($output) + $provisioningState = ($output | ConvertFrom-Json).provisioningState + $gatewayStatus = $jsonOutput.RootElement.GetProperty("gateway").GetProperty("enabled").GetBoolean() + Write-Host "Provisioning State: $provisioningState" + Write-Host "Gateway Status: $gatewayStatus" + if ($provisioningState -eq $SUCCEEDED -and $gatewayStatus -eq $false) { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It "Delete the connected instance" { + az connectedk8s delete -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --force -y + $? | Should -BeTrue + + # Configuration should be removed from the resource model + az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $? | Should -BeFalse + } +} \ No newline at end of file diff --git a/testing/test/configurations/Proxy.Tests.ps1 b/testing/test/configurations/Proxy.Tests.ps1 new file mode 100644 index 00000000000..bda7b06e4bc --- /dev/null +++ b/testing/test/configurations/Proxy.Tests.ps1 @@ -0,0 +1,65 @@ +Describe 'Proxy Scenario' { + BeforeAll { + . $PSScriptRoot/../helper/Constants.ps1 + } + + It 'Check if basic onboarding works correctly with proxy enabled' { + az connectedk8s connect -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup -l $ARC_LOCATION --proxy-skip-range logcollector --no-wait + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $provisioningState = ($output | ConvertFrom-Json).provisioningState + Write-Host "Provisioning State: $provisioningState" + if ($provisioningState -eq $SUCCEEDED) { + $isProxyEnabled = helm get values -n azure-arc-release azure-arc -o yaml | grep isProxyEnabled + Write-Host "$isProxyEnabled" + if ($isProxyEnabled -match "isProxyEnabled: true") { + break + } + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It 'Disable proxy' { + az connectedk8s update -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --disable-proxy + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $provisioningState = ($output | ConvertFrom-Json).provisioningState + Write-Host "Provisioning State: $provisioningState" + if ($provisioningState -eq $SUCCEEDED) { + $isProxyEnabled = helm get values -n azure-arc-release azure-arc -o yaml | grep isProxyEnabled + Write-Host "$isProxyEnabled" + if ($isProxyEnabled -match "isProxyEnabled: false") { + break + } + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It "Delete the connected instance" { + az connectedk8s delete -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --force -y + $? | Should -BeTrue + + # Configuration should be removed from the resource model + az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $? | Should -BeFalse + } +} \ No newline at end of file diff --git a/testing/test/configurations/Troubleshoot.Tests.ps1 b/testing/test/configurations/Troubleshoot.Tests.ps1 new file mode 100644 index 00000000000..c9cb4e26010 --- /dev/null +++ b/testing/test/configurations/Troubleshoot.Tests.ps1 @@ -0,0 +1,40 @@ +Describe 'Troubleshoot Scenario' { + BeforeAll { + . $PSScriptRoot/../helper/Constants.ps1 + } + + It 'Verify cluster onboarding process' { + az connectedk8s connect -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup -l $ARC_LOCATION --no-wait + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $provisioningState = ($output | ConvertFrom-Json).provisioningState + Write-Host "Provisioning State: $provisioningState" + if ($provisioningState -eq $SUCCEEDED) { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It 'Verify troubleshoot command functionality' { + az connectedk8s troubleshoot -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $? | Should -BeTrue + } + + It "Delete the connected instance" { + az connectedk8s delete -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --force -y + $? | Should -BeTrue + + # Configuration should be removed from the resource model + az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $? | Should -BeFalse + } +} \ No newline at end of file diff --git a/testing/test/configurations/WorkloadIdentity.Tests.ps1 b/testing/test/configurations/WorkloadIdentity.Tests.ps1 new file mode 100644 index 00000000000..c728b6a5236 --- /dev/null +++ b/testing/test/configurations/WorkloadIdentity.Tests.ps1 @@ -0,0 +1,239 @@ +Describe 'Onboarding with Workload Identity Scenario' { + BeforeAll { + . $PSScriptRoot/../helper/Constants.ps1 + } + + It 'Check if onboarding works with oidc and workload identity enabled' { + az connectedk8s connect -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup -l $ARC_LOCATION --enable-oidc-issuer --enable-workload-identity --no-wait + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $jsonOutput = [System.Text.Json.JsonDocument]::Parse($output) + $provisioningState = ($output | ConvertFrom-Json).provisioningState + $securityProfile = $jsonOutput.RootElement.GetProperty("securityProfile").GetProperty("workloadIdentity").GetProperty("enabled").GetBoolean() + $oidcIssuerProfile = $jsonOutput.RootElement.GetProperty("oidcIssuerProfile").GetProperty("enabled").GetBoolean() + $issuerUrl = $jsonOutput.RootElement.GetProperty("oidcIssuerProfile").GetProperty("issuerUrl").GetString() + $selfHostedIssuerUrl = $jsonOutput.RootElement.GetProperty("oidcIssuerProfile").GetProperty("selfHostedIssuerUrl").GetString() + $agentState = $jsonOutput.RootElement.GetProperty("arcAgentProfile").GetProperty("agentState").GetString() + Write-Host "Provisioning State: $provisioningState" + Write-Host "Security Profile Status: $securityProfile" + Write-Host "OIDC Issuer Profile Status: $oidcIssuerProfile" + Write-Host "Issuer Url: $issuerUrl" + Write-Host "Self Hosted Issuer Url: $selfHostedIssuerUrl" + Write-Host "Agent State: $agentState" + if ( + $provisioningState -eq $SUCCEEDED -and + $securityProfile -eq $true -and + $oidcIssuerProfile -eq $true -and + ![string]::IsNullOrEmpty($issuerUrl) -and + $issuerUrl -like "*unitedkingdom*" -and + [string]::IsNullOrEmpty($selfHostedIssuerUrl) -and + $agentState -eq $SUCCEEDED + ) { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It 'Disable workload identity' { + az connectedk8s update -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --disable-workload-identity + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $jsonOutput = [System.Text.Json.JsonDocument]::Parse($output) + $provisioningState = ($output | ConvertFrom-Json).provisioningState + $securityProfile = $jsonOutput.RootElement.GetProperty("securityProfile").GetProperty("workloadIdentity").GetProperty("enabled").GetBoolean() + $agentState = $jsonOutput.RootElement.GetProperty("arcAgentProfile").GetProperty("agentState").GetString() + Write-Host "Provisioning State: $provisioningState" + Write-Host "Security Profile Status: $securityProfile" + Write-Host "Agent State: $agentState" + if ($provisioningState -eq $SUCCEEDED -and $securityProfile -eq $false -and $agentState -eq $SUCCEEDED) { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It 'Update the cluster to use workload identity again using update cmd' { + az connectedk8s update -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --enable-workload-identity + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $jsonOutput = [System.Text.Json.JsonDocument]::Parse($output) + $provisioningState = ($output | ConvertFrom-Json).provisioningState + $securityProfile = $jsonOutput.RootElement.GetProperty("securityProfile").GetProperty("workloadIdentity").GetProperty("enabled").GetBoolean() + $agentState = $jsonOutput.RootElement.GetProperty("arcAgentProfile").GetProperty("agentState").GetString() + Write-Host "Provisioning State: $provisioningState" + Write-Host "Security Profile Status: $securityProfile" + Write-Host "Agent State: $agentState" + if ( + $provisioningState -eq $SUCCEEDED -and + $securityProfile -eq $true -and + $agentState -eq $SUCCEEDED + ) { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It "Delete the connected instance" { + az connectedk8s delete -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --force -y + $? | Should -BeTrue + + # Configuration should be removed from the resource model + az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $? | Should -BeFalse + Start-Sleep -Seconds 10 + } +} + +Describe 'Updating with Workload Identity Scenario' { + BeforeAll { + . $PSScriptRoot/../helper/Constants.ps1 + } + + It 'Onboard a cluster to arc' { + az connectedk8s connect -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup -l $ARC_LOCATION --no-wait + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $provisioningState = ($output | ConvertFrom-Json).provisioningState + Write-Host "Provisioning State: $provisioningState" + if ($provisioningState -eq $SUCCEEDED) { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It 'Update the cluster with oidc and workload identity enabled' { + az connectedk8s update -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --enable-oidc-issuer --enable-workload-identity + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $jsonOutput = [System.Text.Json.JsonDocument]::Parse($output) + $provisioningState = ($output | ConvertFrom-Json).provisioningState + $securityProfile = $jsonOutput.RootElement.GetProperty("securityProfile").GetProperty("workloadIdentity").GetProperty("enabled").GetBoolean() + $oidcIssuerProfile = $jsonOutput.RootElement.GetProperty("oidcIssuerProfile").GetProperty("enabled").GetBoolean() + $issuerUrl = $jsonOutput.RootElement.GetProperty("oidcIssuerProfile").GetProperty("issuerUrl").GetString() + $selfHostedIssuerUrl = $jsonOutput.RootElement.GetProperty("oidcIssuerProfile").GetProperty("selfHostedIssuerUrl").GetString() + $agentState = $jsonOutput.RootElement.GetProperty("arcAgentProfile").GetProperty("agentState").GetString() + Write-Host "Provisioning State: $provisioningState" + Write-Host "Security Profile Status: $securityProfile" + Write-Host "OIDC Issuer Profile Status: $oidcIssuerProfile" + Write-Host "Issuer Url: $issuerUrl" + Write-Host "Self Hosted Issuer Url: $selfHostedIssuerUrl" + Write-Host "Agent State: $agentState" + if ( + $provisioningState -eq $SUCCEEDED -and + $securityProfile -eq $true -and + $oidcIssuerProfile -eq $true -and + ![string]::IsNullOrEmpty($issuerUrl) -and + $issuerUrl -like "*unitedkingdom*" -and + [string]::IsNullOrEmpty($selfHostedIssuerUrl) -and + $agentState -eq $SUCCEEDED + ) { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It "Delete the connected instance" { + az connectedk8s delete -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --force -y + $? | Should -BeTrue + + # Configuration should be removed from the resource model + az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $? | Should -BeFalse + Start-Sleep -Seconds 10 + } +} + +Describe 'Creating with Workload Identity Scenario and Self Hosted Issuer' { + BeforeAll { + . $PSScriptRoot/../helper/Constants.ps1 + + $SelfHostedIssuer = "https://eastus.oic.prod-aks.azure.com/fc50e82b-3761-4218-8691-d98bcgb146da/e6c4bf03-84d9-480c-a269-37a41c28c5cb/" + } + + It 'Check if onboarding works with oidc enabled and self-hosted issuer url passed in' { + az connectedk8s connect -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup -l $ARC_LOCATION --enable-oidc-issuer --self-hosted-issuer $SelfHostedIssuer --no-wait + $? | Should -BeTrue + Start-Sleep -Seconds 10 + + # Loop and retry until the configuration installs + $n = 0 + do + { + $output = az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $jsonOutput = [System.Text.Json.JsonDocument]::Parse($output) + $provisioningState = ($output | ConvertFrom-Json).provisioningState + $oidcIssuerProfile = $jsonOutput.RootElement.GetProperty("oidcIssuerProfile").GetProperty("enabled").GetBoolean() + $issuerUrl = $jsonOutput.RootElement.GetProperty("oidcIssuerProfile").GetProperty("issuerUrl").GetString() + $selfHostedIssuerUrl = $jsonOutput.RootElement.GetProperty("oidcIssuerProfile").GetProperty("selfHostedIssuerUrl").GetString() + Write-Host "Provisioning State: $provisioningState" + Write-Host "OIDC Issuer Profile Status: $oidcIssuerProfile" + Write-Host "Issuer Url: $issuerUrl" + Write-Host "Self Hosted Issuer Url: $selfHostedIssuerUrl" + if ( + $provisioningState -eq $SUCCEEDED -and + $oidcIssuerProfile -eq $true -and + [string]::IsNullOrEmpty($issuerUrl) -and + ![string]::IsNullOrEmpty($selfHostedIssuerUrl) -and + $selfHostedIssuerUrl -eq $SelfHostedIssuer + ) { + break + } + Start-Sleep -Seconds 10 + $n += 1 + } while ($n -le $MAX_RETRY_ATTEMPTS) + $n | Should -BeLessOrEqual $MAX_RETRY_ATTEMPTS + } + + It "Delete the connected instance" { + az connectedk8s delete -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup --force -y + $? | Should -BeTrue + + # Configuration should be removed from the resource model + az connectedk8s show -n $ENVCONFIG.arcClusterName -g $ENVCONFIG.resourceGroup + $? | Should -BeFalse + } +} \ No newline at end of file diff --git a/testing/test/helper/Constants.ps1 b/testing/test/helper/Constants.ps1 new file mode 100644 index 00000000000..43006f78a69 --- /dev/null +++ b/testing/test/helper/Constants.ps1 @@ -0,0 +1,5 @@ +$ENVCONFIG = Get-Content -Path $PSScriptRoot/../../settings.json | ConvertFrom-Json + +$MAX_RETRY_ATTEMPTS = 30 +$ARC_LOCATION = "uksouth" +$SUCCEEDED = "Succeeded" \ No newline at end of file