Test plugin
A Test plugin is a mechanism for verifying cluster state before or after a Manifest is applied. It is written in tazuna.yaml and integrated into the tazuna apply flow.
This page summarizes the YAML schema of Test plugins and the spec for the two built-ins (WaitUntil / ExistNonExist).
Placement and Timing
Test plugins can be written in two places in tazuna.yaml.
| Location | Execution timing |
|---|---|
manifests[].tests | Executed immediately after that Manifest is applyed |
spec.tests | Executed after all Manifest applies have completed |
Test plugins are not executed by commands that do not mutate the cluster, such as tazuna build / tazuna check / tazuna state diff. They are also not executed during tazuna destroy.
TestPluginSpec (Common Fields)
The elements of manifests[].tests and spec.tests share the same TestPluginSpec structure.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
type | string | Yes | - | Plugin kind. WaitUntil or ExistNonExist (case-sensitive). |
waitUntil | WaitUntilArgs | Conditional (*) | null | Required when type: WaitUntil. |
existNonExist | ExistNonExistArgs | Conditional (*) | null | Required when type: ExistNonExist. |
minConsecutiveSuccessCount | int | - | 1 | If the test function succeeds this many times consecutively, the entire test plugin is considered successful. 0 is internally corrected to 1. |
minConsecutiveFailureCount | int | - | 0 | If the test function fails this many times consecutively, the entire test plugin is aborted as failure. When 0, this check is not performed, and only timeoutSeconds is the stop condition. |
timeoutSeconds | int | - | Effectively infinite | Overall timeout in seconds. Failure if exceeded. With 0 (unset), effectively unlimited (internally set to about 280 days). |
intervalSeconds | int | - | 0 | Wait seconds between test function re-runs. With 0, re-runs happen immediately. |
(*) The type-to-waitUntil / existNonExist correspondence is verified at runtime. Specifying waitUntil while type: ExistNonExist, or any other mismatch, results in a runtime error.
Evaluation Loop Behavior
All Test plugins run in the following loop.
- Run the test function (plugin-specific logic) once.
- Append the result (success / failure) to the history.
- If the last
minConsecutiveSuccessCountresults are all successes, exit as success. - If
minConsecutiveFailureCountis non-zero and the lastminConsecutiveFailureCountresults are all failures, exit as failure. - If
timeoutSecondshas elapsed, exit as failure. - Sleep for
intervalSecondsseconds and go back to 1 (immediate if0).
If you want to express “one success is enough,” “retry interval is 1 second,” “abort at 60 seconds max,” you get the following.
tests:
- type: WaitUntil
timeoutSeconds: 60
intervalSeconds: 1
waitUntil:
# ...
WaitUntilArgs
A plugin that loops waiting until the specified resource enters “the desired state.” The condition is expressed as a CEL expression.
| Field | Type | Required | Description |
|---|---|---|---|
resource.apiVersion | string | Yes | Target resource apiVersion. Examples: apps/v1, cert-manager.io/v1. |
resource.kind | string | Yes | Target resource kind. Examples: Deployment, Certificate. |
namespace | string | Yes | Target resource namespace. |
name | string | Yes | Target resource name. |
condition | string | Yes | A CEL expression returning a boolean. Within the expression, the retrieved resource is referenced as object, an unstructured map. The expression’s result must be bool (type-checked at compile time). |
Each iteration runs as a “Get the resource → evaluate the CEL expression” pair. Failures to retrieve the resource (including 404) are also treated as a “failure” for that loop iteration.
Common condition examples:
# Deployment is Ready as requested
condition: "object.status.readyReplicas == object.spec.replicas"
# Available conditions has become True (list-evaluation of conditions)
condition: >-
object.status.conditions.exists(c,
c.type == "Available" && c.status == "True")
For the CEL language spec itself, see the official CEL documentation. Tazuna only adds the object variable and the constraint “result must be bool.”
Example (WaitUntil)
tests:
- type: WaitUntil
timeoutSeconds: 120
intervalSeconds: 2
waitUntil:
resource:
apiVersion: apps/v1
kind: Deployment
namespace: ingress-nginx
name: ingress-nginx-controller
condition: "object.status.readyReplicas == object.spec.replicas"
ExistNonExistArgs
A plugin that asserts that the specified resource “should exist” or “should not exist.”
| Field | Type | Required | Description |
|---|---|---|---|
resource.apiVersion | string | Yes | Target resource apiVersion. |
resource.kind | string | Yes | Target resource kind. |
namespace | string | Yes | Target resource namespace. |
name | string | Yes | Target resource name. |
shouldExist | bool | Yes | When true, success if the resource exists. When false, success if it does not exist. |
The decision is made on a single Get result. Existence is judged by whether Get returns NotFound, then matched against shouldExist. Errors other than NotFound (such as insufficient permissions) are treated as a “failure” for that iteration.
Example (ExistNonExist)
tests:
# Assert that the expected resource was installed
- type: ExistNonExist
existNonExist:
resource:
apiVersion: apps/v1
kind: Deployment
namespace: tazuna-managed
name: nginx
shouldExist: true
# Assert that a deprecated resource does not remain
- type: ExistNonExist
timeoutSeconds: 10
intervalSeconds: 1
existNonExist:
resource:
apiVersion: v1
kind: Secret
namespace: tazuna-managed
name: legacy-token
shouldExist: false
Related
- Field for placement:
testsfield intazuna.yaml - Term: Test plugin
- Position in overall architecture: Overall Architecture - Test plugin