Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
20aecd7
add pester tests for connectedk8s cli extension
Mar 18, 2025
40926a3
Pass the force delete param to the API call (#4)
atchutbarli Mar 25, 2025
8f068a8
fix CI testcases for nodepool image issues (#8)
bavneetsingh16 May 23, 2025
ad1ce1d
update python version to 3.13 (#12)
bavneetsingh16 Jul 31, 2025
2121694
changes to support gateway association/disassociation for api version…
bavneetsingh16 Sep 17, 2025
3c08eac
[Azure RBAC] Deprecate 3P mode flags, fix Azure RBAC enablement bug, …
vineeth-thumma Sep 29, 2025
55c2945
bug fix for ffx
hapate Oct 6, 2025
138a0a5
Updated get_mcr_path
hapate Oct 12, 2025
da75dc5
update get_mcr method invoke
hapate Oct 12, 2025
28ce51a
update get_mcr_path helper method to remove aad endpoint resolve
hapate Oct 12, 2025
f1159ec
Update get_mcr_path invoke
hapate Oct 12, 2025
4c6096e
Update get_mcr_path invoke
hapate Oct 12, 2025
67771c2
Update get_mcr_path invoke
hapate Oct 12, 2025
4fb62dd
Add unit test for geT_mcr_path
hapate Oct 12, 2025
b5db13e
fix test for agc cloud
hapate Oct 12, 2025
7109363
addition test for mc cloud
hapate Oct 15, 2025
ed5b5e2
Merge branch 'Azure:main' into main
bavneetsingh16 Oct 15, 2025
9038227
remove hardcoded public ARM endpoint url for fairfax and mooncake (#24)
bavneetsingh16 Oct 15, 2025
23d93d6
Merge branch 'main' into hapate/ffx-mcr-bug-fix
bavneetsingh16 Oct 15, 2025
5fbdd63
fix CI test issues- ruff formatting, linting and delete regex match
Oct 15, 2025
dd3c1f6
Fix MCR postfix to always use '.com'
hapate Oct 15, 2025
f79ffd9
fix CI testcase for mcr path
Oct 15, 2025
b62c8dc
fix ruff formatting
Oct 15, 2025
4013540
Update get_mcr_path for cloud-specific handling
hapate Oct 15, 2025
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
2 changes: 0 additions & 2 deletions src/connectedk8s/azext_connectedk8s/_client_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,13 @@ 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

client = get_mgmt_service_client(
cli_ctx,
KubernetesClient,
base_url="https://management.azure.com",
per_call_policies=[headers_policy],
)
return client
Expand Down
2 changes: 1 addition & 1 deletion src/connectedk8s/azext_connectedk8s/_precheckutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}",
Expand Down
12 changes: 8 additions & 4 deletions src/connectedk8s/azext_connectedk8s/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion src/connectedk8s/azext_connectedk8s/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 23 additions & 0 deletions src/connectedk8s/azext_connectedk8s/tests/unittests/test_utils_.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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()
2 changes: 1 addition & 1 deletion src/k8s-extension/azext_k8s_extension/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 8 additions & 4 deletions src/k8s-extension/azext_k8s_extension/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
9 changes: 9 additions & 0 deletions testing/.gitignore
Original file line number Diff line number Diff line change
@@ -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
30 changes: 30 additions & 0 deletions testing/Bootstrap.ps1
Original file line number Diff line number Diff line change
@@ -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
116 changes: 116 additions & 0 deletions testing/README.md
Original file line number Diff line number Diff line change
@@ -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 <path\to\extensionsuite>
```
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.
99 changes: 99 additions & 0 deletions testing/Test.ps1
Original file line number Diff line number Diff line change
@@ -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
}
}
Binary file added testing/bin/connectedk8s-1.0.0-py3-none-any.whl
Binary file not shown.
3 changes: 3 additions & 0 deletions testing/bin/connectedk8s-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
systemDefaultValues:
extensionoperator:
enabled: true
Binary file not shown.
Binary file added testing/bin/k8s_extension-0.3.0-py3-none-any.whl
Binary file not shown.
2 changes: 2 additions & 0 deletions testing/owners.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
joinnis
nanthi
Loading
Loading