Skip to content
Draft
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: 43 additions & 26 deletions eng/pipelines/templates/jobs/live.tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ parameters:
- name: PersistOidcToken
type: boolean
default: false
# When true, skip the per-run ARM deployment (and its matching teardown) entirely.
# Intended for services whose live tests run against fixed, team-owned accounts resolved
# in BeforeTestSteps rather than provisioned per run -- see sdk/cosmos/pipeline/README.md.
# The azure-sdk live-test tenant is recreated roughly every 90 days, which invalidates the
# service principals and RBAC that New-TestResources.ps1 depends on, so per-run provisioning
# fails until a human re-onboards the tenant.
- name: DisableAzureResourceCreation
type: boolean
default: false

jobs:
- job:
Expand Down Expand Up @@ -143,30 +152,31 @@ jobs:
parameters:
BuildTargetingString: ${{ parameters.BuildTargetingString }}

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

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

- ${{ each directory in coalesce(parameters.TestResourceDirectories, split(parameters.ServiceDirectory, '|')) }}:
- template: /eng/common/TestResources/deploy-test-resources.yml
parameters:
Location: ${{ coalesce(parameters.Location, parameters.CloudConfig.Location) }}
ServiceDirectory: '${{ directory }}'
SubscriptionConfiguration: $(SubscriptionConfiguration)
ArmTemplateParameters: $(ArmTemplateParameters)
UseFederatedAuth: ${{ parameters.UseFederatedAuth }}
PersistOidcToken: ${{ parameters.PersistOidcToken }}
ServiceConnection: ${{ parameters.CloudConfig.ServiceConnection }}
EnvVars:
Pool: $(Pool)
${{ insert }}: ${{ parameters.EnvVars }}

# This is a heuristic to detect compiled requirements in the service
# directory. If compiled requirements are found, install dependencies for
# and configure cibuildwheel.
Expand Down Expand Up @@ -241,13 +251,20 @@ jobs:
TestProxy: ${{ parameters.TestProxy }}
UseFederatedAuth: ${{ parameters.UseFederatedAuth }}
ServiceConnection: ${{ parameters.CloudConfig.ServiceConnection }}
# build-test.yml runs these immediately before/after the test task, in the same job,
# so a BeforeTestSteps step can publish pipeline variables that the test task then
# picks up as environment variables. These were declared here but never forwarded,
# which silently dropped anything a service passed in via archetype-sdk-tests.yml.
BeforeTestSteps: ${{ parameters.BeforeTestSteps }}
AfterTestSteps: ${{ parameters.AfterTestSteps }}

- ${{ each directory in coalesce(parameters.TestResourceDirectories, split(parameters.ServiceDirectory, '|')) }}:
- template: /eng/common/TestResources/remove-test-resources.yml
parameters:
ServiceDirectory: '${{ directory }}'
SubscriptionConfiguration: $(SubscriptionConfiguration)
UseFederatedAuth: ${{ parameters.UseFederatedAuth }}
ServiceConnection: ${{ parameters.CloudConfig.ServiceConnection }}
- ${{ if not(parameters.DisableAzureResourceCreation) }}:
- ${{ each directory in coalesce(parameters.TestResourceDirectories, split(parameters.ServiceDirectory, '|')) }}:
- template: /eng/common/TestResources/remove-test-resources.yml
parameters:
ServiceDirectory: '${{ directory }}'
SubscriptionConfiguration: $(SubscriptionConfiguration)
UseFederatedAuth: ${{ parameters.UseFederatedAuth }}
ServiceConnection: ${{ parameters.CloudConfig.ServiceConnection }}

- ${{ parameters.PostSteps }}
7 changes: 7 additions & 0 deletions eng/pipelines/templates/stages/archetype-sdk-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ parameters:
- name: PersistOidcToken
type: boolean
default: false
# Skip the per-run ARM deployment and its teardown for this stage. Use when the service's
# live tests bind to fixed, team-owned accounts (resolved in BeforeTestSteps) instead of
# provisioning per run. See sdk/cosmos/pipeline/README.md for the Cosmos implementation.
- name: DisableAzureResourceCreation
type: boolean
default: false

extends:
template: /eng/pipelines/templates/stages/1es-redirect.yml
Expand Down Expand Up @@ -146,6 +152,7 @@ extends:
CheckEnv: ${{ parameters.CheckEnv }}
UseFederatedAuth: ${{ parameters.UseFederatedAuth }}
PersistOidcToken: ${{ parameters.PersistOidcToken }}
DisableAzureResourceCreation: ${{ parameters.DisableAzureResourceCreation }}
MatrixConfigs:
# Enumerate platforms and additional platforms based on supported clouds (sparse platform<-->cloud matrix).
- ${{ each config in parameters.MatrixConfigs }}:
Expand Down
1 change: 1 addition & 0 deletions sdk/cosmos/azure-cosmos/pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ markers =
cosmosEmulator: marks tests as depending in Cosmos DB Emulator.
cosmosLong: marks tests to be run on a Cosmos DB live account.
cosmosQuery: marks tests running queries on Cosmos DB live account.
cosmosSearchQuery: marks tests running full text and vector search queries on a Cosmos DB live account.
cosmosAADLong: marks AAD tests for the standard live-account lane.
cosmosAADSplit: marks AAD tests for partition split scenarios.
cosmosAADMultiRegion: marks AAD tests for multi-region scenarios.
Expand Down
18 changes: 9 additions & 9 deletions sdk/cosmos/azure-cosmos/tests/test_aad.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ def capturing_get_token(self, *scopes, **kwargs):
def test_override_scope_no_fallback(self):
"""When override scope is provided, only that scope is used and no fallback occurs."""
override_scope = "https://my.custom.scope/.default"
os.environ["AZURE_COSMOS_AAD_SCOPE_OVERRIDE"] = override_scope
previous_env = test_config.set_environment_variables(AZURE_COSMOS_AAD_SCOPE_OVERRIDE=override_scope)
self.addCleanup(test_config.restore_environment_variables, previous_env)

def action(scopes_captured):
credential = CosmosEmulatorCredential()
Expand All @@ -152,7 +153,6 @@ def action(scopes_captured):
try:
assert all(scope == override_scope for scope in scopes), f"Expected only override scope(s), got: {scopes}"
finally:
del os.environ["AZURE_COSMOS_AAD_SCOPE_OVERRIDE"]
try:
container.delete_item(item='Item_10', partition_key='pk')
except Exception:
Expand All @@ -162,7 +162,8 @@ def action(scopes_captured):
def test_override_scope_auth_error_no_fallback(self):
"""When override scope is provided and auth fails, no fallback to other scopes occurs."""
override_scope = "https://my.custom.scope/.default"
os.environ["AZURE_COSMOS_AAD_SCOPE_OVERRIDE"] = override_scope
previous_env = test_config.set_environment_variables(AZURE_COSMOS_AAD_SCOPE_OVERRIDE=override_scope)
self.addCleanup(test_config.restore_environment_variables, previous_env)

class FailingCredential(CosmosEmulatorCredential):
def get_token(self, *scopes, **kwargs):
Expand All @@ -178,16 +179,14 @@ def action(scopes_captured):
return None

scopes, _ = self._run_with_scope_capture(FailingCredential, action)
try:
assert scopes == [override_scope], f"Expected only override scope, got: {scopes}"
finally:
del os.environ["AZURE_COSMOS_AAD_SCOPE_OVERRIDE"]
assert scopes == [override_scope], f"Expected only override scope, got: {scopes}"

@_skip_on_non_emulator
def test_account_scope_only(self):
"""When account scope is provided, only that scope is used."""
account_scope = "https://localhost/.default"
os.environ["AZURE_COSMOS_AAD_SCOPE_OVERRIDE"] = ""
previous_env = test_config.set_environment_variables(AZURE_COSMOS_AAD_SCOPE_OVERRIDE="")
self.addCleanup(test_config.restore_environment_variables, previous_env)

def action(scopes_captured):
credential = CosmosEmulatorCredential()
Expand All @@ -212,7 +211,8 @@ def test_account_scope_fallback_on_error(self):
"""When account scope is provided and auth fails, fallback to default scope occurs."""
account_scope = "https://localhost/.default"
fallback_scope = "https://cosmos.azure.com/.default"
os.environ["AZURE_COSMOS_AAD_SCOPE_OVERRIDE"] = ""
previous_env = test_config.set_environment_variables(AZURE_COSMOS_AAD_SCOPE_OVERRIDE="")
self.addCleanup(test_config.restore_environment_variables, previous_env)

class FallbackCredential(CosmosEmulatorCredential):
def __init__(self):
Expand Down
14 changes: 8 additions & 6 deletions sdk/cosmos/azure-cosmos/tests/test_aad_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ async def capturing_get_token(self, *scopes, **kwargs):
async def test_override_scope_no_fallback_async(self):
"""When override scope is provided, only that scope is used and no fallback occurs."""
override_scope = "https://my.custom.scope/.default"
os.environ["AZURE_COSMOS_AAD_SCOPE_OVERRIDE"] = override_scope
previous_env = test_config.set_environment_variables(AZURE_COSMOS_AAD_SCOPE_OVERRIDE=override_scope)
self.addCleanup(test_config.restore_environment_variables, previous_env)

async def action(scopes_captured):
credential = CosmosEmulatorCredential()
Expand All @@ -156,7 +157,6 @@ async def action(scopes_captured):
try:
assert all(scope == override_scope for scope in scopes), f"Expected only override scope, got: {scopes}"
finally:
del os.environ["AZURE_COSMOS_AAD_SCOPE_OVERRIDE"]
try:
await container.delete_item(item='Item_20', partition_key='pk')
except Exception:
Expand All @@ -166,7 +166,8 @@ async def action(scopes_captured):
async def test_override_scope_no_fallback_on_error_async(self):
"""When override scope is provided and auth fails, no fallback occurs."""
override_scope = "https://my.custom.scope/.default"
os.environ["AZURE_COSMOS_AAD_SCOPE_OVERRIDE"] = override_scope
previous_env = test_config.set_environment_variables(AZURE_COSMOS_AAD_SCOPE_OVERRIDE=override_scope)
self.addCleanup(test_config.restore_environment_variables, previous_env)

class FailingCredential(CosmosEmulatorCredential):
async def get_token(self, *scopes, **kwargs):
Expand All @@ -190,7 +191,6 @@ async def action(scopes_captured):
try:
assert all(scope == override_scope for scope in scopes), f"Expected only override scope, got: {scopes}"
finally:
del os.environ["AZURE_COSMOS_AAD_SCOPE_OVERRIDE"]
try:
await container.delete_item(item='Item_21', partition_key='pk')
except Exception:
Expand All @@ -200,7 +200,8 @@ async def action(scopes_captured):
async def test_account_scope_only_async(self):
"""When account scope is provided, only that scope is used."""
account_scope = "https://localhost/.default"
os.environ["AZURE_COSMOS_AAD_SCOPE_OVERRIDE"] = ""
previous_env = test_config.set_environment_variables(AZURE_COSMOS_AAD_SCOPE_OVERRIDE="")
self.addCleanup(test_config.restore_environment_variables, previous_env)

async def action(scopes_captured):
credential = CosmosEmulatorCredential()
Expand All @@ -227,7 +228,8 @@ async def test_account_scope_fallback_on_error_async(self):
"""When account scope is provided and auth fails, fallback to default scope occurs."""
account_scope = "https://localhost/.default"
fallback_scope = "https://cosmos.azure.com/.default"
os.environ["AZURE_COSMOS_AAD_SCOPE_OVERRIDE"] = ""
previous_env = test_config.set_environment_variables(AZURE_COSMOS_AAD_SCOPE_OVERRIDE="")
self.addCleanup(test_config.restore_environment_variables, previous_env)

class FallbackCredential(CosmosEmulatorCredential):
def __init__(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def get_token(self, *scopes, **kwargs):


@pytest.mark.cosmosEmulator
@pytest.mark.cosmosLong
@pytest.mark.cosmosAADLong
class TestAADInferenceServiceLazyInit(unittest.TestCase):
"""Verify AAD client construction succeeds without the semantic reranker env var.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ async def get_token(self, *scopes, **kwargs):


@pytest.mark.cosmosEmulator
@pytest.mark.cosmosLong
@pytest.mark.cosmosAADLong
class TestAADInferenceServiceLazyInitAsync(unittest.IsolatedAsyncioTestCase):
"""Verify async AAD client construction succeeds without the semantic reranker env var.

Expand Down
6 changes: 3 additions & 3 deletions sdk/cosmos/azure-cosmos/tests/test_auto_scale.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def test_autoscale_create_container(self):
self.created_database.delete_container(container_id)

def test_autoscale_create_database(self):
database_id = "db_auto_scale_" + str(uuid.uuid4())
database_id = test_config.unique_database_id("auto-scale")
try:
# Testing auto_scale_settings for the create_database method
created_database = self.key_client.create_database(database_id, offer_throughput=ThroughputProperties(
Expand All @@ -87,7 +87,7 @@ def test_autoscale_create_database(self):
self.key_client.delete_database(created_database.id)

# Testing auto_scale_settings for the create_database_if_not_exists method
database_id = "db_auto_scale_2_" + str(uuid.uuid4())
database_id = test_config.unique_database_id("auto-scale-2")
created_database = self.key_client.create_database_if_not_exists(database_id,
offer_throughput=ThroughputProperties(
auto_scale_max_throughput=9000,
Expand All @@ -101,7 +101,7 @@ def test_autoscale_create_database(self):
self.key_client.delete_database(database_id)

def test_autoscale_replace_throughput(self):
database_id = "replace_db" + str(uuid.uuid4())
database_id = test_config.unique_database_id("replace-db")
container_id = None
try:
created_database = self.key_client.create_database(database_id, offer_throughput=ThroughputProperties(
Expand Down
6 changes: 3 additions & 3 deletions sdk/cosmos/azure-cosmos/tests/test_auto_scale_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ async def test_autoscale_create_database_async(self):
database_id = None
try:
# Testing auto_scale_settings for the create_database method
database_id = "db1_" + str(uuid.uuid4())
database_id = test_config.unique_database_id("db1")
created_database = await self.key_client.create_database(database_id, offer_throughput=ThroughputProperties(
auto_scale_max_throughput=5000,
auto_scale_increment_percent=0))
Expand All @@ -95,7 +95,7 @@ async def test_autoscale_create_database_async(self):
await self.key_client.delete_database(created_database.id)

# Testing auto_scale_settings for the create_database_if_not_exists method
database_id = "db2_" + str(uuid.uuid4())
database_id = test_config.unique_database_id("db2")
created_database = await self.key_client.create_database_if_not_exists(database_id, offer_throughput=ThroughputProperties(
auto_scale_max_throughput=9000,
auto_scale_increment_percent=11))
Expand All @@ -108,7 +108,7 @@ async def test_autoscale_create_database_async(self):
await self.key_client.delete_database(database_id)

async def test_replace_throughput_async(self):
database_id = "replace_db" + str(uuid.uuid4())
database_id = test_config.unique_database_id("replace-db")
container_id = None
try:
created_database = await self.key_client.create_database(database_id, offer_throughput=ThroughputProperties(
Expand Down
Loading
Loading