Skip to content

Commit 60b8f86

Browse files
authored
Merge pull request #1491 from fluxcd/feat-dependon-cel
Extend the readiness evaluation of dependencies with CEL expressions
2 parents 8ec3ec3 + fd63b52 commit 60b8f86

File tree

14 files changed

+714
-224
lines changed

14 files changed

+714
-224
lines changed

api/v1/kustomization_types.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ type KustomizationSpec struct {
4949
// +optional
5050
CommonMetadata *CommonMetadata `json:"commonMetadata,omitempty"`
5151

52-
// DependsOn may contain a meta.NamespacedObjectReference slice
52+
// DependsOn may contain a DependencyReference slice
5353
// with references to Kustomization resources that must be ready before this
5454
// Kustomization can be reconciled.
5555
// +optional
56-
DependsOn []meta.NamespacedObjectReference `json:"dependsOn,omitempty"`
56+
DependsOn []DependencyReference `json:"dependsOn,omitempty"`
5757

5858
// Decrypt Kubernetes secrets before applying them on the cluster.
5959
// +optional
@@ -333,9 +333,19 @@ func (in Kustomization) GetDeletionPolicy() string {
333333
return in.Spec.DeletionPolicy
334334
}
335335

336-
// GetDependsOn returns the list of dependencies across-namespaces.
336+
// GetDependsOn returns the dependencies as a list of meta.NamespacedObjectReference.
337+
//
338+
// This function makes the Kustomization type conformant with the meta.ObjectWithDependencies interface
339+
// and allows the controller-runtime to index Kustomizations by their dependencies.
337340
func (in Kustomization) GetDependsOn() []meta.NamespacedObjectReference {
338-
return in.Spec.DependsOn
341+
deps := make([]meta.NamespacedObjectReference, len(in.Spec.DependsOn))
342+
for i := range in.Spec.DependsOn {
343+
deps[i] = meta.NamespacedObjectReference{
344+
Name: in.Spec.DependsOn[i].Name,
345+
Namespace: in.Spec.DependsOn[i].Namespace,
346+
}
347+
}
348+
return deps
339349
}
340350

341351
// GetConditions returns the status conditions of the object.

api/v1/reference_types.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ limitations under the License.
1616

1717
package v1
1818

19-
import "fmt"
19+
import (
20+
"fmt"
21+
)
2022

2123
// CrossNamespaceSourceReference contains enough information to let you locate the
2224
// typed Kubernetes resource object at cluster level.
@@ -40,9 +42,31 @@ type CrossNamespaceSourceReference struct {
4042
Namespace string `json:"namespace,omitempty"`
4143
}
4244

45+
// String returns a string representation of the CrossNamespaceSourceReference
46+
// in the format "Kind/Name" or "Kind/Namespace/Name" if Namespace is set.
4347
func (s *CrossNamespaceSourceReference) String() string {
4448
if s.Namespace != "" {
4549
return fmt.Sprintf("%s/%s/%s", s.Kind, s.Namespace, s.Name)
4650
}
4751
return fmt.Sprintf("%s/%s", s.Kind, s.Name)
4852
}
53+
54+
// DependencyReference defines a Kustomization dependency on another Kustomization resource.
55+
type DependencyReference struct {
56+
// Name of the referent.
57+
// +required
58+
Name string `json:"name"`
59+
60+
// Namespace of the referent, defaults to the namespace of the Kustomization
61+
// resource object that contains the reference.
62+
// +optional
63+
Namespace string `json:"namespace,omitempty"`
64+
65+
// ReadyExpr is a CEL expression that can be used to assess the readiness
66+
// of a dependency. When specified, the built-in readiness check
67+
// is replaced by the logic defined in the CEL expression.
68+
// To make the CEL expression additive to the built-in readiness check,
69+
// the feature gate `AdditiveCELDependencyCheck` must be set to `true`.
70+
// +optional
71+
ReadyExpr string `json:"readyExpr,omitempty"`
72+
}

api/v1/zz_generated.deepcopy.go

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/kustomize.toolkit.fluxcd.io_kustomizations.yaml

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,20 +123,28 @@ spec:
123123
type: string
124124
dependsOn:
125125
description: |-
126-
DependsOn may contain a meta.NamespacedObjectReference slice
126+
DependsOn may contain a DependencyReference slice
127127
with references to Kustomization resources that must be ready before this
128128
Kustomization can be reconciled.
129129
items:
130-
description: |-
131-
NamespacedObjectReference contains enough information to locate the referenced Kubernetes resource object in any
132-
namespace.
130+
description: DependencyReference defines a Kustomization dependency
131+
on another Kustomization resource.
133132
properties:
134133
name:
135134
description: Name of the referent.
136135
type: string
137136
namespace:
138-
description: Namespace of the referent, when not specified it
139-
acts as LocalObjectReference.
137+
description: |-
138+
Namespace of the referent, defaults to the namespace of the Kustomization
139+
resource object that contains the reference.
140+
type: string
141+
readyExpr:
142+
description: |-
143+
ReadyExpr is a CEL expression that can be used to assess the readiness
144+
of a dependency. When specified, the built-in readiness check
145+
is replaced by the logic defined in the CEL expression.
146+
To make the CEL expression additive to the built-in readiness check,
147+
the feature gate `AdditiveCELDependencyCheck` must be set to `true`.
140148
type: string
141149
required:
142150
- name

docs/api/v1/kustomize.md

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,14 @@ overridden if its key matches a common one.</p>
8989
<td>
9090
<code>dependsOn</code><br>
9191
<em>
92-
<a href="https://godoc.org/github.com/fluxcd/pkg/apis/meta#NamespacedObjectReference">
93-
[]github.com/fluxcd/pkg/apis/meta.NamespacedObjectReference
92+
<a href="#kustomize.toolkit.fluxcd.io/v1.DependencyReference">
93+
[]DependencyReference
9494
</a>
9595
</em>
9696
</td>
9797
<td>
9898
<em>(Optional)</em>
99-
<p>DependsOn may contain a meta.NamespacedObjectReference slice
99+
<p>DependsOn may contain a DependencyReference slice
100100
with references to Kustomization resources that must be ready before this
101101
Kustomization can be reconciled.</p>
102102
</td>
@@ -609,6 +609,67 @@ field.</p>
609609
</table>
610610
</div>
611611
</div>
612+
<h3 id="kustomize.toolkit.fluxcd.io/v1.DependencyReference">DependencyReference
613+
</h3>
614+
<p>
615+
(<em>Appears on:</em>
616+
<a href="#kustomize.toolkit.fluxcd.io/v1.KustomizationSpec">KustomizationSpec</a>)
617+
</p>
618+
<p>DependencyReference defines a Kustomization dependency on another Kustomization resource.</p>
619+
<div class="md-typeset__scrollwrap">
620+
<div class="md-typeset__table">
621+
<table>
622+
<thead>
623+
<tr>
624+
<th>Field</th>
625+
<th>Description</th>
626+
</tr>
627+
</thead>
628+
<tbody>
629+
<tr>
630+
<td>
631+
<code>name</code><br>
632+
<em>
633+
string
634+
</em>
635+
</td>
636+
<td>
637+
<p>Name of the referent.</p>
638+
</td>
639+
</tr>
640+
<tr>
641+
<td>
642+
<code>namespace</code><br>
643+
<em>
644+
string
645+
</em>
646+
</td>
647+
<td>
648+
<em>(Optional)</em>
649+
<p>Namespace of the referent, defaults to the namespace of the Kustomization
650+
resource object that contains the reference.</p>
651+
</td>
652+
</tr>
653+
<tr>
654+
<td>
655+
<code>readyExpr</code><br>
656+
<em>
657+
string
658+
</em>
659+
</td>
660+
<td>
661+
<em>(Optional)</em>
662+
<p>ReadyExpr is a CEL expression that can be used to assess the readiness
663+
of a dependency. When specified, the built-in readiness check
664+
is replaced by the logic defined in the CEL expression.
665+
To make the CEL expression additive to the built-in readiness check,
666+
the feature gate <code>AdditiveCELDependencyCheck</code> must be set to <code>true</code>.</p>
667+
</td>
668+
</tr>
669+
</tbody>
670+
</table>
671+
</div>
672+
</div>
612673
<h3 id="kustomize.toolkit.fluxcd.io/v1.KustomizationSpec">KustomizationSpec
613674
</h3>
614675
<p>
@@ -647,14 +708,14 @@ overridden if its key matches a common one.</p>
647708
<td>
648709
<code>dependsOn</code><br>
649710
<em>
650-
<a href="https://godoc.org/github.com/fluxcd/pkg/apis/meta#NamespacedObjectReference">
651-
[]github.com/fluxcd/pkg/apis/meta.NamespacedObjectReference
711+
<a href="#kustomize.toolkit.fluxcd.io/v1.DependencyReference">
712+
[]DependencyReference
652713
</a>
653714
</em>
654715
</td>
655716
<td>
656717
<em>(Optional)</em>
657-
<p>DependsOn may contain a meta.NamespacedObjectReference slice
718+
<p>DependsOn may contain a DependencyReference slice
658719
with references to Kustomization resources that must be ready before this
659720
Kustomization can be reconciled.</p>
660721
</td>

docs/spec/v1/kustomizations.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,51 @@ is running before deploying applications inside the mesh.
487487
**Note:** Circular dependencies between Kustomizations must be avoided,
488488
otherwise the interdependent Kustomizations will never be applied on the cluster.
489489

490+
#### Dependency Ready Expression
491+
492+
`.spec.dependsOn[].readyExpr` is an optional field that can be used to define a CEL expression
493+
to determine the readiness of a Kustomization dependency.
494+
495+
This is helpful for when custom logic is needed to determine if a dependency is ready.
496+
For example, when performing a lockstep upgrade, the `readyExpr` can be used to
497+
verify that a dependency has a matching version label before proceeding with the
498+
reconciliation of the dependent Kustomization.
499+
500+
```yaml
501+
apiVersion: kustomize.toolkit.fluxcd.io/v1
502+
kind: Kustomization
503+
metadata:
504+
name: app-backend
505+
namespace: apps
506+
labels:
507+
app/version: v1.2.3
508+
---
509+
apiVersion: kustomize.toolkit.fluxcd.io/v1
510+
kind: Kustomization
511+
metadata:
512+
name: app-frontend
513+
namespace: apps
514+
labels:
515+
app/version: v1.2.3
516+
spec:
517+
dependsOn:
518+
- name: app-backend
519+
readyExpr: >
520+
dep.metadata.labels['app/version'] == self.metadata.labels['app/version'] &&
521+
dep.status.conditions.filter(e, e.type == 'Ready').all(e, e.status == 'True') &&
522+
dep.metadata.generation == dep.status.observedGeneration
523+
```
524+
525+
The CEL expression contains the following variables:
526+
527+
- `dep`: The dependency Kustomization object being evaluated.
528+
- `self`: The Kustomization object being reconciled.
529+
530+
**Note:** When `readyExpr` is specified, the built-in readiness check is replaced by the logic
531+
defined in the CEL expression. You can configure the controller to run both the CEL expression
532+
evaluation and the built-in readiness check, with the `AdditiveCELDependencyCheck`
533+
[feature gate](https://fluxcd.io/flux/components/kustomize/options/#feature-gates).
534+
490535
### Service Account reference
491536

492537
`.spec.serviceAccountName` is an optional field used to specify the

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ require (
3434
github.com/fluxcd/pkg/testserver v0.11.0
3535
github.com/fluxcd/source-controller/api v1.6.0
3636
github.com/getsops/sops/v3 v3.10.2
37+
github.com/google/cel-go v0.23.2
3738
github.com/hashicorp/vault/api v1.20.0
3839
github.com/onsi/gomega v1.37.0
3940
github.com/opencontainers/go-digest v1.0.0
@@ -147,11 +148,10 @@ require (
147148
github.com/go-openapi/jsonpointer v0.21.1 // indirect
148149
github.com/go-openapi/jsonreference v0.21.0 // indirect
149150
github.com/go-openapi/swag v0.23.1 // indirect
150-
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
151+
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
151152
github.com/gogo/protobuf v1.3.2 // indirect
152153
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
153154
github.com/google/btree v1.1.3 // indirect
154-
github.com/google/cel-go v0.23.2 // indirect
155155
github.com/google/gnostic-models v0.7.0 // indirect
156156
github.com/google/go-cmp v0.7.0 // indirect
157157
github.com/google/go-containerregistry v0.20.6 // indirect

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
258258
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
259259
github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw=
260260
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
261-
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
262-
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
261+
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
262+
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
263263
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
264264
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
265265
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=

internal/controller/constants.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,7 @@ limitations under the License.
1616

1717
package controller
1818

19-
const OCIArtifactOriginRevisionAnnotation = "org.opencontainers.image.revision"
19+
const (
20+
OCIArtifactOriginRevisionAnnotation = "org.opencontainers.image.revision"
21+
TerminalErrorMessage = "Reconciliation failed terminally due to configuration error"
22+
)

0 commit comments

Comments
 (0)