From 7bfcce91ec692d0d75e2784ec4f9e18d11277882 Mon Sep 17 00:00:00 2001 From: Thomas Flament Date: Fri, 20 Mar 2026 12:15:04 +0100 Subject: [PATCH] add @Exclusive tag to prevent cluster-mutating tests from running in parallel Issue: ZENKO-5228 --- tests/ctst/HOW_TO_WRITE_TESTS.md | 18 +++++++++++++----- tests/ctst/common/hooks.ts | 16 +++++++++++++++- tests/ctst/features/azureArchive.feature | 1 + tests/ctst/features/bucketWebsite.feature | 1 + tests/ctst/features/pra.feature | 1 + 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/tests/ctst/HOW_TO_WRITE_TESTS.md b/tests/ctst/HOW_TO_WRITE_TESTS.md index 4f5bbe74d6..904e032bf2 100644 --- a/tests/ctst/HOW_TO_WRITE_TESTS.md +++ b/tests/ctst/HOW_TO_WRITE_TESTS.md @@ -36,13 +36,16 @@ restart of multiple services, must be created before the test starts, or in a dedicated set of tests, that is, a set of test executed before all tests having a specific tag used for identifying the feature(s). -Note: Testing the reconfiguration of the environment is recommended, but it -should be done carefully to not affect other tests. +When a scenario *must* reconfigure the environment (e.g., create or modify +locations, add overlay endpoints), tag it with `@Exclusive`. This ensures no +other scenario runs in parallel while the exclusive scenario executes, and the +exclusive scenario only starts once all running scenarios have finished. See +the implementation in `common/hooks.ts`. -## 4. Do not use `atMostOnePicklePerTag`. +## 4. Avoid unnecessary parallel restrictions. -If a set of scenario requires the use of `atMostOnePicklePerTag`, they won't -be executed in parallel, which is: +Adding `atMostOnePicklePerTag` for a set of scenarios means they won't be +executed in parallel, which is: - Not realistic for the production environment. - Not efficient for the test execution: the duration of tests will suffer. @@ -59,6 +62,11 @@ possible. Solutions exist: relative checks. - As a last resort, we might have a dedicated test suite. +Note: `@Exclusive` (see **Rule #3**) is an exception — it is reserved for +scenarios that mutate cluster-wide state (location creation, overlay changes) +and cannot be made idempotent because the operator reconciliation affects all +running pods. Use it sparingly. + ## 5. Focus on validating features. We only want to assert against externally visible state, as given in the diff --git a/tests/ctst/common/hooks.ts b/tests/ctst/common/hooks.ts index 8ec981682a..ef3779e351 100644 --- a/tests/ctst/common/hooks.ts +++ b/tests/ctst/common/hooks.ts @@ -32,7 +32,21 @@ const noParallelRun = atMostOnePicklePerTag([ ...replicationLockTags ]); -setParallelCanAssign(noParallelRun); +const EXCLUSIVE_TAG = '@Exclusive'; + +function hasTag(pickle: { tags: readonly { name: string }[] }, tagName: string): boolean { + return pickle.tags.some(t => t.name === tagName); +} + +setParallelCanAssign((pickle, runningPickles) => { + if (runningPickles.some(p => hasTag(p, EXCLUSIVE_TAG))) { + return false; + } + if (hasTag(pickle, EXCLUSIVE_TAG)) { + return runningPickles.length === 0; + } + return noParallelRun(pickle, runningPickles); +}); Before(async function (this: Zenko, scenario: ITestCaseHookParameter) { this.resetSaved(); diff --git a/tests/ctst/features/azureArchive.feature b/tests/ctst/features/azureArchive.feature index 9839c5fbfd..6cc1487bc5 100644 --- a/tests/ctst/features/azureArchive.feature +++ b/tests/ctst/features/azureArchive.feature @@ -45,6 +45,7 @@ Feature: Azure Archive @Flaky @AzureArchive @ColdStorage + @Exclusive Scenario Outline: Create, read, update and delete azure archive location Given an azure archive location "" And a "" bucket diff --git a/tests/ctst/features/bucketWebsite.feature b/tests/ctst/features/bucketWebsite.feature index e0b8e0a468..5049a123d9 100644 --- a/tests/ctst/features/bucketWebsite.feature +++ b/tests/ctst/features/bucketWebsite.feature @@ -3,6 +3,7 @@ Feature: Bucket Websites @2.6.0 @PreMerge @BucketWebsite + @Exclusive Scenario Outline: Bucket Website CRUD # The scenario should test that we can put a bucket website configuration on a bucket # send an index.html diff --git a/tests/ctst/features/pra.feature b/tests/ctst/features/pra.feature index 0199b137b2..cb3a126b8a 100644 --- a/tests/ctst/features/pra.feature +++ b/tests/ctst/features/pra.feature @@ -5,6 +5,7 @@ Feature: PRA operations @Dmf @PRA @ColdStorage + @Exclusive Scenario Outline: PRA (nominal case) # Prepare objects in the primary site Given a "" bucket