Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 42 additions & 27 deletions eng/pipelines/templates/jobs/live.tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ parameters:
type: boolean
- name: PersistOidcToken
type: boolean
# When true, skips build-test-resource-config.yml/deploy-test-resources.yml (and thus any
# per-run ARM deployment / Azure tenant auth) and runs PreTestRunSteps in their place. Used
# by legs that test against fixed, self-owned accounts instead of resources deployed fresh
# each run (see sdk/cosmos/pipeline/README.md for the motivating example).
- name: DisableAzureResourceCreation
type: boolean
default: false
- name: PreTestRunSteps
type: object
default: []

jobs:
- job:
Expand Down Expand Up @@ -72,29 +82,34 @@ jobs:

- ${{ parameters.PreSteps }}

- template: /eng/common/TestResources/build-test-resource-config.yml
parameters:
SubscriptionConfiguration: ${{ parameters.CloudConfig.SubscriptionConfiguration }}
SubscriptionConfigurations: ${{ parameters.CloudConfig.SubscriptionConfigurations }}
SubscriptionConfigurationFilePaths: ${{ parameters.CloudConfig.SubscriptionConfigurationFilePaths }}
EnvVars:
Pool: $(Pool)
${{insert}}: ${{ parameters.EnvVars }}

- template: /eng/common/TestResources/deploy-test-resources.yml
parameters:
${{ if or(parameters.Location, parameters.CloudConfig.Location) }}:
Location: ${{ coalesce(parameters.Location, parameters.CloudConfig.Location) }}
ServiceDirectory: ${{ parameters.ServiceDirectory }}
SubscriptionConfiguration: $(SubscriptionConfiguration)
ArmTemplateParameters: $(ArmTemplateParameters)
UseFederatedAuth: ${{ parameters.UseFederatedAuth }}
ServiceConnection: ${{ parameters.CloudConfig.ServiceConnection }}
SubscriptionConfigurationFilePaths: ${{ parameters.CloudConfig.SubscriptionConfigurationFilePaths}}
PersistOidcToken: ${{ parameters.PersistOidcToken }}
EnvVars:
Pool: $(Pool)
${{insert}}: ${{ parameters.EnvVars }}
- ${{ if not(parameters.DisableAzureResourceCreation) }}:
- template: /eng/common/TestResources/build-test-resource-config.yml
parameters:
SubscriptionConfiguration: ${{ parameters.CloudConfig.SubscriptionConfiguration }}
SubscriptionConfigurations: ${{ parameters.CloudConfig.SubscriptionConfigurations }}
SubscriptionConfigurationFilePaths: ${{ parameters.CloudConfig.SubscriptionConfigurationFilePaths }}
EnvVars:
Pool: $(Pool)
${{insert}}: ${{ parameters.EnvVars }}

- template: /eng/common/TestResources/deploy-test-resources.yml
parameters:
${{ if or(parameters.Location, parameters.CloudConfig.Location) }}:
Location: ${{ coalesce(parameters.Location, parameters.CloudConfig.Location) }}
ServiceDirectory: ${{ parameters.ServiceDirectory }}
SubscriptionConfiguration: $(SubscriptionConfiguration)
ArmTemplateParameters: $(ArmTemplateParameters)
UseFederatedAuth: ${{ parameters.UseFederatedAuth }}
ServiceConnection: ${{ parameters.CloudConfig.ServiceConnection }}
SubscriptionConfigurationFilePaths: ${{ parameters.CloudConfig.SubscriptionConfigurationFilePaths}}
PersistOidcToken: ${{ parameters.PersistOidcToken }}
EnvVars:
Pool: $(Pool)
${{insert}}: ${{ parameters.EnvVars }}
- ${{ else }}:
# No ARM deployment and no Azure tenant auth for this leg - resolve a fixed,
# self-owned account instead (see sdk/cosmos/pipeline/README.md).
- ${{ parameters.PreTestRunSteps }}

# To allow tests to run in parallel to Pack, we don't reuse the PackageInfo directory
# from the Pack job. We just let each test leg create its own PackageInfo directory.
Expand All @@ -111,7 +126,7 @@ jobs:
- ${{ if parameters.UseFederatedAuth }}:
- task: AzurePowerShell@5
displayName: "Test Packages - Federated Auth"
condition: and(succeeded(), eq(variables['CI_HAS_DEPLOYED_RESOURCES'], 'true'))
condition: and(succeeded(), or(eq(variables['CI_HAS_DEPLOYED_RESOURCES'], 'true'), eq(${{ parameters.DisableAzureResourceCreation }}, true)))
timeoutInMinutes: ${{ parameters.TimeoutInMinutes }}
env:
CIBW_BUILD_VERBOSITY: 3
Expand Down Expand Up @@ -139,7 +154,7 @@ jobs:
- ${{ else }}:
- task: Powershell@2
displayName: "Test Packages"
condition: and(succeeded(), eq(variables['CI_HAS_DEPLOYED_RESOURCES'], 'true'))
condition: and(succeeded(), or(eq(variables['CI_HAS_DEPLOYED_RESOURCES'], 'true'), eq(${{ parameters.DisableAzureResourceCreation }}, true)))
timeoutInMinutes: ${{ parameters.TimeoutInMinutes }}
env:
CIBW_BUILD_VERBOSITY: 3
Expand All @@ -154,14 +169,14 @@ jobs:

- task: Powershell@2
displayName: Convert Test Results to JUnit XML
condition: and(succeededOrFailed(), eq(variables['CI_HAS_DEPLOYED_RESOURCES'], 'true'))
condition: and(succeededOrFailed(), or(eq(variables['CI_HAS_DEPLOYED_RESOURCES'], 'true'), eq(${{ parameters.DisableAzureResourceCreation }}, true)))
inputs:
pwsh: true
filePath: $(Build.SourcesDirectory)/eng/scripts/Convert-TestResultsToJUnit.ps1

- task: PublishTestResults@2
displayName: Publish Test Results
condition: and(succeededOrFailed(), eq(variables['CI_HAS_DEPLOYED_RESOURCES'], 'true'), eq(variables['HasJUnitTestResults'], 'true'))
condition: and(succeededOrFailed(), or(eq(variables['CI_HAS_DEPLOYED_RESOURCES'], 'true'), eq(${{ parameters.DisableAzureResourceCreation }}, true)), eq(variables['HasJUnitTestResults'], 'true'))
inputs:
testResultsFormat: JUnit
testResultsFiles: '**/test-results/junit/*.xml'
Expand Down
48 changes: 48 additions & 0 deletions eng/pipelines/templates/stages/archetype-sdk-client.yml

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Daniel Jurek (@danieljurek) or Ben Broderick Phillips (@benbp) can you review this please? I think you helped them originally so I don't have as much context.

Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,21 @@ parameters:
Selection: sparse
NonSparseParameters: RustToolchainName
GenerateVMJobs: true
# A second, independent set of live-test matrix configs for legs that test against fixed,
# self-owned resources instead of resources deployed fresh each run. Unlike
# LiveTestMatrixConfigs, jobs generated from these configs skip ARM deployment entirely
# (DisableAzureResourceCreation: true) and run PreTestRunSteps in its place, with
# UseFederatedAuth forced off since no Azure tenant auth is needed. See
# sdk/cosmos/pipeline/README.md for the motivating example.
- name: FixedAccountMatrixConfigs
type: object
default: []
# Steps to run instead of ARM deployment for jobs generated from FixedAccountMatrixConfigs
# (e.g. resolving a fixed account's endpoint/key from a secret). Ignored if
# FixedAccountMatrixConfigs is empty.
- name: PreTestRunSteps
type: object
default: []
- name: AdditionalMatrixConfigs
type: object
default: []
Expand Down Expand Up @@ -171,6 +186,39 @@ extends:
SubscriptionConfigurations: ${{ cloud.value.SubscriptionConfigurations }}
SubscriptionConfigurationFilePaths: ${{ cloud.value.SubscriptionConfigurationFilePaths }}

- ${{ if ne(length(parameters.FixedAccountMatrixConfigs), 0) }}:
- template: /eng/common/pipelines/templates/jobs/generate-job-matrix.yml
parameters:
GenerateJobName: generate_job_matrix_fixed_account
JobTemplatePath: /eng/pipelines/templates/jobs/live.tests.yml
AdditionalParameters:
ServiceDirectory: ${{ parameters.ServiceDirectory }}
TimeoutInMinutes: ${{ parameters.TestTimeoutInMinutes }}
EnvVars: ${{ parameters.EnvVars }}
PreSteps: ${{ parameters.PreSteps }}
PostSteps: ${{ parameters.PostSteps }}
Location: ${{ parameters.Location }}
# Fixed, self-owned accounts need no Azure tenant auth at all.
UseFederatedAuth: false
PersistOidcToken: false
DisableAzureResourceCreation: true
PreTestRunSteps: ${{ parameters.PreTestRunSteps }}
MatrixConfigs:
- ${{ parameters.FixedAccountMatrixConfigs }}
MatrixFilters:
- ${{ cloud.value.MatrixFilters }}
- ${{ parameters.MatrixFilters }}
MatrixReplace:
- ${{ cloud.value.MatrixReplace }}
- ${{ parameters.MatrixReplace }}
CloudConfig:
Cloud: ${{ cloud.key }}
Location: ${{ coalesce(cloud.value.Location, parameters.Location) }}
ServiceConnection: ${{ coalesce(cloud.value.ServiceConnection, lower(format('azure-sdk-tests-{0}', cloud.key))) }}
SubscriptionConfiguration: ${{ cloud.value.SubscriptionConfiguration }}
SubscriptionConfigurations: ${{ cloud.value.SubscriptionConfigurations }}
SubscriptionConfigurationFilePaths: ${{ cloud.value.SubscriptionConfigurationFilePaths }}

# The Prerelease and Release stages are conditioned on:
# 1. Internal trigger, not Pull Request trigger
# 2. Not weekly build
Expand Down
9 changes: 8 additions & 1 deletion sdk/cosmos/.cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,14 @@
"vout",
"Xpert",
"xpert",
"yxxx"
"yxxx",
"issecret",
"multiwrite",
"rustflags",
"sdkci",
"setvariable",
"singlewrite",
"whatif"
],
"ignorePaths": [
"live-platform-matrix.json",
Expand Down
10 changes: 10 additions & 0 deletions sdk/cosmos/azure_data_cosmos/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

// cspell:ignore enableaadauthentication

// Registers custom cfgs used by this crate's integration tests.
//
// Some CI/build setups enable `-W unexpected-cfgs`, and in newer Rust toolchains
Expand All @@ -9,4 +12,11 @@ fn main() {
println!(
"cargo:rustc-check-cfg=cfg(test_category, values(\"emulator\", \"emulator_vnext\", \"emulator_inmemory\", \"emulator_inmemory_gateway_v2\", \"multi_write\", \"split\", \"binary_encoding\", \"gateway_v2\", \"gateway_v2_multi_region\"))"
);
// Marker cfg set by test setups where the target Cosmos account is provisioned
// for AAD data-plane access (local emulator started with /enableaadauthentication,
// or a live account whose bicep deployment created the data-plane role assignment).
// Fixed self-owned live accounts do not currently have that role assignment and
// therefore do not set this cfg, which causes AAD data-plane tests to be ignored
// on those legs.
println!("cargo:rustc-check-cfg=cfg(cosmos_aad_supported)");
}
35 changes: 10 additions & 25 deletions sdk/cosmos/azure_data_cosmos/tests/emulator_tests/cosmos_aad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
//! mirrors the data-plane RBAC role provisioned in `test-resources.bicep`, which
//! grants item/metadata data actions but **not** management-plane permissions.
//!
//! Because the standard `test_category="emulator"` gate is used, the same tests
//! run against the local emulator (Build stage, with the emulator started using
//! `/enableaadauthentication`) and against live accounts (LiveTest stage), where
//! the framework selects a real Entra ID credential via
//! `azure_core_test::credentials::from_env`.
//! Because these tests need AAD data-plane access, they gate on the
//! `cosmos_aad_supported` cfg (set by the local emulator setup when started
//! with `/enableaadauthentication`, and by bicep-provisioned live accounts
//! that include the Cosmos data-plane role assignment). Fixed self-owned live
//! accounts without that role assignment do not set this cfg, so these tests
//! are skipped on those legs.

use super::framework;

Expand Down Expand Up @@ -48,16 +49,8 @@ struct AadTestItem {
/// invoked for the Cosmos scope, guarding against silently exercising key auth.
#[tokio::test]
#[cfg_attr(
not(any(
test_category = "emulator",
test_category = "emulator_vnext",
test_category = "emulator_inmemory"
)),
ignore = "requires test_category 'emulator', 'emulator_vnext', or 'emulator_inmemory'"
)]
#[cfg_attr(
test_category = "emulator_inmemory",
ignore = "hosted in-memory emulator authentication is deferred to PR3"
any(not(cosmos_aad_supported), test_category = "emulator_inmemory"),
ignore = "requires an AAD-enabled Cosmos target (emulator with /enableaadauthentication, or a live account with the Cosmos data-plane role assignment); hosted in-memory emulator authentication is deferred to a follow-up PR"
)]
pub async fn aad_item_crud_roundtrip() -> Result<(), Box<dyn Error>> {
TestClient::run_with_unique_db(
Expand Down Expand Up @@ -157,16 +150,8 @@ pub async fn aad_item_crud_roundtrip() -> Result<(), Box<dyn Error>> {
/// the `readMetadata` data action the SDK requires on its first request.
#[tokio::test]
#[cfg_attr(
not(any(
test_category = "emulator",
test_category = "emulator_vnext",
test_category = "emulator_inmemory"
)),
ignore = "requires test_category 'emulator', 'emulator_vnext', or 'emulator_inmemory'"
)]
#[cfg_attr(
test_category = "emulator_inmemory",
ignore = "hosted in-memory emulator authentication is deferred to PR3"
any(not(cosmos_aad_supported), test_category = "emulator_inmemory"),
ignore = "requires an AAD-enabled Cosmos target (emulator with /enableaadauthentication, or a live account with the Cosmos data-plane role assignment); hosted in-memory emulator authentication is deferred to a follow-up PR"
)]
pub async fn aad_read_container_metadata() -> Result<(), Box<dyn Error>> {
TestClient::run_with_unique_db(
Expand Down
28 changes: 26 additions & 2 deletions sdk/cosmos/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ extends:
RUST_BACKTRACE: '1'
# Live budget for the binary-encoding round-trip fuzzer
# (azure_data_cosmos/tests/binary_roundtrip_fuzzer.rs). Only consumed on
# the `binary_encoding` live leg (live-platform-matrix.json); a no-op
# the `binary_encoding` live leg (live-legacy-arm-matrix.json); a no-op
# elsewhere. Each iteration exercises 3 encoding configs x 4 point ops, so
# 200 => ~2400 round-trips — bounded to fit the live-test time cap. Bump it
# for a deeper soak.
Expand Down Expand Up @@ -87,11 +87,35 @@ extends:
Path: sdk/cosmos/inmemory-emulator-matrix.json
Selection: all
GenerateVMJobs: true
LiveTestMatrixConfigs:
# Cosmos_live_test runs against fixed, self-owned accounts (see
# sdk/cosmos/pipeline/README.md) instead of resources deployed fresh each run,
# so it lives in FixedAccountMatrixConfigs rather than LiveTestMatrixConfigs.
# PreTestRunSteps resolves the account selected by each matrix leg's
# AccountSelector from the rust-ci secret, in place of
# ARM deployment (DisableAzureResourceCreation: true is set automatically for
# this leg by archetype-sdk-client.yml).
FixedAccountMatrixConfigs:
- Name: Cosmos_live_test
Path: sdk/cosmos/live-platform-matrix.json
Selection: sparse
GenerateVMJobs: true
Comment on lines +97 to 101

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The scope of this PR is the move to fixed accounts; adding a sweeper is a separate concern with its own design questions (schedule, age threshold, safety against a concurrent run, which identity runs it).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it is not completely orthogonal - for example one step to take now might be to not just use UUID based names - but prefix them with some tiemstamp - so, that any async sweeper could delete let's say db/collections that were created >12 hours ago? Not necessarily blocking for this PR - but worth thinking about this because it will become a hot topic as soon as this PR is merged.

PreTestRunSteps:
- template: /sdk/cosmos/pipeline/resolve-test-account-steps.yml
parameters:
AccountSelector: $(AccountSelector)
LiveTestMatrixConfigs:
# Legs that still use ARM-deployed per-run Cosmos accounts (not migrated
# to fixed self-owned accounts):
# * Thin-client (GatewayV2) legs use $(thinclient-test-endpoint)/
# $(thinclient-test-key) for the thin-client itself, but their primary
# client still needs an ARM-provisioned account.
# * Binary-encoding round-trip fuzz leg exercises encoding boundaries
# against a fresh account and is short-lived.
# Left on the legacy per-run path intentionally.
- Name: Cosmos_live_arm
Path: sdk/cosmos/live-legacy-arm-matrix.json
Selection: all
GenerateVMJobs: true
# Dedicated live leg that runs the full integration suite with the primary
# (data-plane) client authenticated via Entra ID (AAD) instead of the
# account key. `AZURE_COSMOS_AUTH_MODE=aad` surfaces as a job env var and
Expand Down
3 changes: 3 additions & 0 deletions sdk/cosmos/eng/scripts/Invoke-CosmosTestCleanup.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,7 @@ $env:AZURE_COSMOS_INMEMORY_ACCOUNT_ENDPOINT = $null
# The next package's setup will re-add the correct flag from COSMOS_RUSTFLAGS
# (or from AZURE_COSMOS_EMULATOR_FLAVOR=vnext when running the vnext stage).
$env:RUSTFLAGS = $env:RUSTFLAGS -replace '\s*--cfg=test_category="[^"]*"', ''
# Also strip the cosmos_aad_supported marker cfg so the next package's setup
# starts from a clean slate.
$env:RUSTFLAGS = $env:RUSTFLAGS -replace '\s*--cfg=cosmos_aad_supported', ''
Write-Host "RUSTFLAGS after cleanup: $env:RUSTFLAGS"
6 changes: 3 additions & 3 deletions sdk/cosmos/eng/scripts/Invoke-CosmosTestSetup.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ if ($env:AZURE_COSMOS_EMULATOR_FLAVOR -eq 'vnext') {
$env:AZURE_COSMOS_CONNECTION_STRING = "AccountEndpoint=http://localhost:8081;AccountKey=$vnextKey;"
Write-Host "Set AZURE_COSMOS_CONNECTION_STRING to vnext emulator endpoint."
}
$env:RUSTFLAGS = "$($env:RUSTFLAGS) --cfg=test_category=`"emulator_vnext`""
$env:RUSTFLAGS = "$($env:RUSTFLAGS) --cfg=test_category=`"emulator_vnext`" --cfg=cosmos_aad_supported"
Write-Host "RUSTFLAGS set to: $env:RUSTFLAGS"
$env:RUST_TEST_THREADS = "1"
return
Expand Down Expand Up @@ -299,7 +299,7 @@ if ($IsWindows) {

# Set environment variables for the tests
$env:AZURE_COSMOS_CONNECTION_STRING = "emulator"
$env:RUSTFLAGS = "$($env:RUSTFLAGS) --cfg=test_category=`"emulator`""
$env:RUSTFLAGS = "$($env:RUSTFLAGS) --cfg=test_category=`"emulator`" --cfg=cosmos_aad_supported"
Write-Host "RUSTFLAGS set to: $env:RUSTFLAGS"

# Run tests single-threaded to avoid env var contamination from proxy tests.
Expand Down Expand Up @@ -352,7 +352,7 @@ elseif (Get-Command "docker" -ErrorAction SilentlyContinue) {

# Set environment variables for the tests
$env:AZURE_COSMOS_CONNECTION_STRING = "emulator"
$env:RUSTFLAGS = "$($env:RUSTFLAGS) --cfg=test_category=`"emulator`""
$env:RUSTFLAGS = "$($env:RUSTFLAGS) --cfg=test_category=`"emulator`" --cfg=cosmos_aad_supported"
Write-Host "RUSTFLAGS set to: $env:RUSTFLAGS"

# Run tests single-threaded to avoid env var contamination from proxy tests.
Expand Down
23 changes: 23 additions & 0 deletions sdk/cosmos/live-legacy-arm-matrix.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"displayNames": {},
"matrix": {
"Agent": {
"ubuntu": {
"OSVmImage": "env:LINUXVMIMAGE",
"Pool": "env:LINUXPOOL"
}
},
"RustToolchainName": ["stable"],
"Account Settings": {
"Session SingleRegion GatewayV2": {
"ArmTemplateParameters": "@{ defaultConsistencyLevel = 'Session'; testCategory = 'gateway_v2' }"
},
"Session MultiRegion GatewayV2": {
"ArmTemplateParameters": "@{ defaultConsistencyLevel = 'Session'; enableMultipleRegions = $true; testCategory = 'gateway_v2_multi_region' }"
},
"Session SingleWrite BinaryEncodingRoundtripFuzz": {
"ArmTemplateParameters": "@{ defaultConsistencyLevel = 'Session'; enableAutomaticFailover = $false; testCategory = 'binary_encoding' }"
}
}
}
}
Loading
Loading