DAG Execution via dependsOn
Tazuna has two execution models for tazuna.yaml’s manifests[]: a mode that runs them sequentially in declaration order, and a lightweight DAG mode using dependsOn. This page summarizes how the two are switched and what ordering guarantees and parallelism the DAG mode provides.
Switching rules
When no Manifest in tazuna.yaml declares dependsOn, manifests are applied one at a time in declaration order as before. This is the default behavior, kept for backward compatibility.
spec:
manifests:
- name: cni
type: kustomize
path: ./cni
- name: ingress
type: helmfile
path: ./ingress
- name: app
type: kustomize
path: ./app
In this case Tazuna applies them one at a time in the order cni -> ingress -> app.
If even one Manifest has a dependsOn, the Runner switches to DAG mode.
spec:
manifests:
- name: cni
type: kustomize
path: ./cni
- name: cert-manager
type: helmfile
path: ./cert-manager
dependsOn: [cni]
- name: ingress
type: helmfile
path: ./ingress
dependsOn: [cni]
- name: app
type: kustomize
path: ./app
dependsOn: [cert-manager, ingress]
In this case, the Runner builds the following layers.
| Layer | Manifest | Execution |
|---|---|---|
| Layer 1 | cni | Runs only one |
| Layer 2 | cert-manager / ingress | Parallel execution |
| Layer 3 | app | Runs only one |
Topological sort
In DAG mode, topological sorting is done with Kahn’s algorithm. Each iteration takes the set of nodes with in-degree 0 as “one layer”; after that layer finishes, it decrements the in-degree of the nodes that depended on them, and this repeats.
Manifests within a layer are stably sorted so they are emitted in their original declaration order, so the output order does not waver no matter how many times you run the same tazuna.yaml (the parallel execution itself is unordered).
Parallelism within a layer
Manifests that fall into the same layer are applied in parallel via goroutines. Because there is a barrier at each layer boundary, ordering guarantees such as “install app only after waiting for cert-manager” are not broken.
If apply fails within a layer, errors are aggregated after waiting for the other goroutines in that layer to finish. Mid-run cancellation is not currently performed.
Validation
During tazuna check and tazuna apply, dependsOn is subject to the following checks.
- Each listed Manifest name must exist in the full set of Manifests after
includesexpansion. - A Manifest must not include itself in
dependsOn. - The dependency graph must contain no cycle.
If any of these is violated, Tazuna exits with an error without touching the cluster at all.
Why dependsOn rather than parallel
Earlier versions of Tazuna had a Manifest type called type: parallel. It was “a box that runs child Manifests in parallel,” but it had the following problems.
- Dependencies could only be expressed through nested
parallelstructures, making complex cases hard to write. - Manifests under
parallelwere outside the scope of state management (State / drift detection). - “Ordering dependency,” “parallelism,” and “grouping” were all mixed into a single field.
dependsOn rewrites this in the vocabulary of a graph: nodes (Manifests) and edges (dependencies). Parallelism is derived automatically from the dependency graph, so users only need to declare “order” and can leave parallelization to the runtime. type: parallel has been removed in this refactor.
Best practices
- Declare a dependency only on a “Manifest that needs its prerequisite resources to be Ready.” If you merely want to group manifests,
tagsis more appropriate. - Before writing a long chain, consider once whether “this is really just waiting on a CRD, so the Test plugin’s
WaitUntilcould serve instead.” - To avoid circular dependencies, the trick is to use
dependsOnonly in one direction, from lower to higher layers (CNI -> cert-manager -> ingress -> app).
Related
- Overall architecture: Overall Architecture
- Schema:
tazuna.yaml- Manifest - The apply itself:
tazuna apply