Introduce label selector for watching ConfigMaps and Secrets
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
This commit is contained in:
parent
0971d38c41
commit
7c18470676
|
|
@ -4,7 +4,7 @@ go 1.24.0
|
|||
|
||||
require (
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.11.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.17.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.18.0
|
||||
k8s.io/apiextensions-apiserver v0.33.2
|
||||
k8s.io/apimachinery v0.33.2
|
||||
sigs.k8s.io/controller-runtime v0.21.0
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.11.0 h1:0IzDgxZkc4v+5SDNCvgZhfwfkdkQLPXCner7TNaJFWE=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.11.0/go.mod h1:j302mJGDww8cn9qvMsRQ0LJ1HPAPs/IlX7CSsoJV7BI=
|
||||
github.com/fluxcd/pkg/apis/meta v1.17.0 h1:KVMDyJQj1NYCsppsFUkbJGMnKxsqJVpnKBFolHf/q8E=
|
||||
github.com/fluxcd/pkg/apis/meta v1.17.0/go.mod h1:97l3hTwBpJbXBY+wetNbqrUsvES8B1jGioKcBUxmqd8=
|
||||
github.com/fluxcd/pkg/apis/meta v1.18.0 h1:ACHrMIjlcioE9GKS7NGk62KX4NshqNewr8sBwMcXABs=
|
||||
github.com/fluxcd/pkg/apis/meta v1.18.0/go.mod h1:97l3hTwBpJbXBY+wetNbqrUsvES8B1jGioKcBUxmqd8=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
|
|
|
|||
|
|
@ -458,6 +458,10 @@ a list). You can read more about the available formats and limitations in the
|
|||
For JSON strings, the [limitations are the same as while using `helm`](https://github.com/helm/helm/issues/5618)
|
||||
and require you to escape the full JSON string (including `=`, `[`, `,`, `.`).
|
||||
|
||||
To make a HelmRelease react immediately to changes in the referenced Secret
|
||||
or ConfigMap see [this](#reacting-immediately-to-configuration-dependencies)
|
||||
section.
|
||||
|
||||
#### Inline values
|
||||
|
||||
`.spec.values` is an optional field to inline values within a HelmRelease. When
|
||||
|
|
@ -836,6 +840,10 @@ Two authentication alternatives are available:
|
|||
building a kubeconfig dynamically with parameters stored in a Kubernetes
|
||||
ConfigMap in the same namespace as the HelmRelease via workload identity.
|
||||
|
||||
To make a HelmRelease react immediately to changes in the referenced Secret
|
||||
or ConfigMap see [this](#reacting-immediately-to-configuration-dependencies)
|
||||
section.
|
||||
|
||||
When both `.spec.kubeConfig` and
|
||||
[`.spec.serviceAccountName`](#service-account-reference) are specified,
|
||||
the controller will impersonate the ServiceAccount on the target cluster,
|
||||
|
|
@ -1590,6 +1598,28 @@ with the values from the referenced ConfigMaps and/or Secrets.
|
|||
are referenced in the HelmRelease `.spec.valuesFrom` field, so exercise caution
|
||||
when using this command.
|
||||
|
||||
### Reacting immediately to configuration dependencies
|
||||
|
||||
To trigger a Helm release upgrade when changes occur in referenced
|
||||
Secrets or ConfigMaps, you can set the following label on the
|
||||
Secret or ConfigMap:
|
||||
|
||||
```yaml
|
||||
metadata:
|
||||
labels:
|
||||
reconcile.fluxcd.io/watch: Enabled
|
||||
```
|
||||
|
||||
An alternative to labeling every Secret or ConfigMap is
|
||||
setting the `--watch-configs-label-selector=owner!=helm`
|
||||
[flag](https://fluxcd.io/flux/components/helm/options/#flags)
|
||||
in helm-controller, which allows watching all Secrets and
|
||||
ConfigMaps except for Helm storage Secrets.
|
||||
|
||||
**Note**: An upgrade will be triggered for an event on a referenced
|
||||
Secret/ConfigMap even if it's marked as optional in the `.spec.valuesFrom`
|
||||
field, including deletion events.
|
||||
|
||||
## HelmRelease Status
|
||||
|
||||
### Events
|
||||
|
|
|
|||
8
go.mod
8
go.mod
|
|
@ -21,11 +21,11 @@ require (
|
|||
github.com/fluxcd/pkg/apis/acl v0.8.0
|
||||
github.com/fluxcd/pkg/apis/event v0.18.0
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.11.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.17.0
|
||||
github.com/fluxcd/pkg/auth v0.21.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.18.0
|
||||
github.com/fluxcd/pkg/auth v0.22.0
|
||||
github.com/fluxcd/pkg/cache v0.10.0
|
||||
github.com/fluxcd/pkg/chartutil v1.7.0
|
||||
github.com/fluxcd/pkg/runtime v0.69.0
|
||||
github.com/fluxcd/pkg/chartutil v1.8.0
|
||||
github.com/fluxcd/pkg/runtime v0.72.0
|
||||
github.com/fluxcd/pkg/ssa v0.51.0
|
||||
github.com/fluxcd/pkg/testserver v0.11.0
|
||||
github.com/fluxcd/source-controller/api v1.6.0
|
||||
|
|
|
|||
16
go.sum
16
go.sum
|
|
@ -148,16 +148,16 @@ github.com/fluxcd/pkg/apis/event v0.18.0 h1:PNbWk9gvX8gMIi6VsJapnuDO+giLEeY+6olL
|
|||
github.com/fluxcd/pkg/apis/event v0.18.0/go.mod h1:7S/DGboLolfbZ6stO6dcDhG1SfkPWQ9foCULvbiYpiA=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.11.0 h1:0IzDgxZkc4v+5SDNCvgZhfwfkdkQLPXCner7TNaJFWE=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.11.0/go.mod h1:j302mJGDww8cn9qvMsRQ0LJ1HPAPs/IlX7CSsoJV7BI=
|
||||
github.com/fluxcd/pkg/apis/meta v1.17.0 h1:KVMDyJQj1NYCsppsFUkbJGMnKxsqJVpnKBFolHf/q8E=
|
||||
github.com/fluxcd/pkg/apis/meta v1.17.0/go.mod h1:97l3hTwBpJbXBY+wetNbqrUsvES8B1jGioKcBUxmqd8=
|
||||
github.com/fluxcd/pkg/auth v0.21.0 h1:ckAQqP12wuptXEkMY18SQKWEY09m9e6yI0mEMsDV15M=
|
||||
github.com/fluxcd/pkg/auth v0.21.0/go.mod h1:MXmpsXT97c874HCw5hnfqFUP7TsG8/Ss1vFrk8JccfM=
|
||||
github.com/fluxcd/pkg/apis/meta v1.18.0 h1:ACHrMIjlcioE9GKS7NGk62KX4NshqNewr8sBwMcXABs=
|
||||
github.com/fluxcd/pkg/apis/meta v1.18.0/go.mod h1:97l3hTwBpJbXBY+wetNbqrUsvES8B1jGioKcBUxmqd8=
|
||||
github.com/fluxcd/pkg/auth v0.22.0 h1:h+tjYm4w/tC7Rvxph/A2wplOXAEohQCbh5u1TLMrEQE=
|
||||
github.com/fluxcd/pkg/auth v0.22.0/go.mod h1:YEAHpBFuW5oLlH9ekuJaQdnJ2Q3A7Ny8kha3WY7QMnY=
|
||||
github.com/fluxcd/pkg/cache v0.10.0 h1:M+OGDM4da1cnz7q+sZSBtkBJHpiJsLnKVmR9OdMWxEY=
|
||||
github.com/fluxcd/pkg/cache v0.10.0/go.mod h1:pPXRzQUDQagsCniuOolqVhnAkbNgYOg8d2cTliPs7ME=
|
||||
github.com/fluxcd/pkg/chartutil v1.7.0 h1:hzcqJ/60jj3WwYHDEHiFyrAfe2kZZ3GWZepd305ZpWo=
|
||||
github.com/fluxcd/pkg/chartutil v1.7.0/go.mod h1:hfSQ5JPmT6oUEXUthuWb51oCqtQjbnt8i6GqBGYchfU=
|
||||
github.com/fluxcd/pkg/runtime v0.69.0 h1:5gPY95NSFI34GlQTj0+NHjOFpirSwviCUb9bM09b5nA=
|
||||
github.com/fluxcd/pkg/runtime v0.69.0/go.mod h1:ug+pat+I4wfOBuCy2E/pLmBNd3kOOo4cP2jxnxefPwY=
|
||||
github.com/fluxcd/pkg/chartutil v1.8.0 h1:kDR87A1FyhUNgm48nIUrx2CKbEtix7tI8j7gESQdiTU=
|
||||
github.com/fluxcd/pkg/chartutil v1.8.0/go.mod h1:yeZzhTNogNAbGlSge2RiaACOCQt5GwentCq3yFYgEUU=
|
||||
github.com/fluxcd/pkg/runtime v0.72.0 h1:9JCto84iL2FziuTuuvDwvS+cfIzGhHOk25y8ulXpNOs=
|
||||
github.com/fluxcd/pkg/runtime v0.72.0/go.mod h1:iGhdaEq+lMJQTJNAFEPOU4gUJ7kt3yeDcJPZy7O9IUw=
|
||||
github.com/fluxcd/pkg/ssa v0.51.0 h1:sFarxKZcS0J8sjq9qvs/r+1XiJqNgRodEiPjV75F8R4=
|
||||
github.com/fluxcd/pkg/ssa v0.51.0/go.mod h1:v+h9RC0JxWIqMTK2Eo+8Nh700AXyZChZ2TiLVj4tf3M=
|
||||
github.com/fluxcd/pkg/testserver v0.11.0 h1:a/kxpFqv7XQxZjwVPP3voooRmSd/3ipLVolK0xUIxXQ=
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ type HelmReleaseReconcilerOptions struct {
|
|||
HTTPRetry int
|
||||
DependencyRequeueInterval time.Duration
|
||||
RateLimiter workqueue.TypedRateLimiter[reconcile.Request]
|
||||
WatchConfigsPredicate predicate.Predicate
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
@ -117,6 +118,11 @@ var (
|
|||
)
|
||||
|
||||
func (r *HelmReleaseReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, opts HelmReleaseReconcilerOptions) error {
|
||||
const (
|
||||
indexConfigMap = ".metadata.configMap"
|
||||
indexSecret = ".metadata.secret"
|
||||
)
|
||||
|
||||
// Index the HelmRelease by the Source reference they point to.
|
||||
if err := mgr.GetFieldIndexer().IndexField(ctx, &v2.HelmRelease{}, v2.SourceIndexKey,
|
||||
func(o client.Object) []string {
|
||||
|
|
@ -133,6 +139,46 @@ func (r *HelmReleaseReconciler) SetupWithManager(ctx context.Context, mgr ctrl.M
|
|||
return err
|
||||
}
|
||||
|
||||
// Index the HelmRelease by the ConfigMap references they point to.
|
||||
if err := mgr.GetFieldIndexer().IndexField(ctx, &v2.HelmRelease{}, indexConfigMap,
|
||||
func(o client.Object) []string {
|
||||
obj := o.(*v2.HelmRelease)
|
||||
namespace := obj.GetNamespace()
|
||||
var keys []string
|
||||
if kc := obj.Spec.KubeConfig; kc != nil && kc.ConfigMapRef != nil {
|
||||
keys = append(keys, fmt.Sprintf("%s/%s", namespace, kc.ConfigMapRef.Name))
|
||||
}
|
||||
for _, ref := range obj.Spec.ValuesFrom {
|
||||
if ref.Kind == "ConfigMap" {
|
||||
keys = append(keys, fmt.Sprintf("%s/%s", namespace, ref.Name))
|
||||
}
|
||||
}
|
||||
return keys
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Index the HelmRelease by the Secret references they point to.
|
||||
if err := mgr.GetFieldIndexer().IndexField(ctx, &v2.HelmRelease{}, indexSecret,
|
||||
func(o client.Object) []string {
|
||||
obj := o.(*v2.HelmRelease)
|
||||
namespace := obj.GetNamespace()
|
||||
var keys []string
|
||||
if kc := obj.Spec.KubeConfig; kc != nil && kc.SecretRef != nil {
|
||||
keys = append(keys, fmt.Sprintf("%s/%s", namespace, kc.SecretRef.Name))
|
||||
}
|
||||
for _, ref := range obj.Spec.ValuesFrom {
|
||||
if ref.Kind == "Secret" {
|
||||
keys = append(keys, fmt.Sprintf("%s/%s", namespace, ref.Name))
|
||||
}
|
||||
}
|
||||
return keys
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.requeueDependency = opts.DependencyRequeueInterval
|
||||
r.artifactFetchRetries = opts.HTTPRetry
|
||||
|
||||
|
|
@ -150,6 +196,16 @@ func (r *HelmReleaseReconciler) SetupWithManager(ctx context.Context, mgr ctrl.M
|
|||
handler.EnqueueRequestsFromMapFunc(r.requestsForOCIRrepositoryChange),
|
||||
builder.WithPredicates(intpredicates.SourceRevisionChangePredicate{}),
|
||||
).
|
||||
WatchesMetadata(
|
||||
&corev1.ConfigMap{},
|
||||
handler.EnqueueRequestsFromMapFunc(r.requestsForConfigDependency(indexConfigMap)),
|
||||
builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}, opts.WatchConfigsPredicate),
|
||||
).
|
||||
WatchesMetadata(
|
||||
&corev1.Secret{},
|
||||
handler.EnqueueRequestsFromMapFunc(r.requestsForConfigDependency(indexSecret)),
|
||||
builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}, opts.WatchConfigsPredicate),
|
||||
).
|
||||
WithOptions(controller.Options{
|
||||
RateLimiter: opts.RateLimiter,
|
||||
}).
|
||||
|
|
@ -877,6 +933,36 @@ func (r *HelmReleaseReconciler) requestsForOCIRrepositoryChange(ctx context.Cont
|
|||
return reqs
|
||||
}
|
||||
|
||||
// requestsForConfigDependency enqueues requests for watched ConfigMaps or Secrets
|
||||
// according to the specified index.
|
||||
func (r *HelmReleaseReconciler) requestsForConfigDependency(
|
||||
index string) func(ctx context.Context, o client.Object) []reconcile.Request {
|
||||
|
||||
return func(ctx context.Context, o client.Object) []reconcile.Request {
|
||||
// List HelmReleases that have a dependency on the ConfigMap or Secret.
|
||||
var list v2.HelmReleaseList
|
||||
if err := r.List(ctx, &list, client.MatchingFields{
|
||||
index: client.ObjectKeyFromObject(o).String(),
|
||||
}); err != nil {
|
||||
ctrl.LoggerFrom(ctx).Error(err, "failed to list HelmReleases for config dependency change",
|
||||
"index", index, "objectRef", map[string]string{
|
||||
"name": o.GetName(),
|
||||
"namespace": o.GetNamespace(),
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Enqueue requests for each HelmRelease in the list.
|
||||
reqs := make([]reconcile.Request, 0, len(list.Items))
|
||||
for i := range list.Items {
|
||||
reqs = append(reqs, reconcile.Request{
|
||||
NamespacedName: client.ObjectKeyFromObject(&list.Items[i]),
|
||||
})
|
||||
}
|
||||
return reqs
|
||||
}
|
||||
}
|
||||
|
||||
func isSourceReady(obj sourcev1.Source) (bool, string) {
|
||||
if o, ok := obj.(conditions.Getter); ok {
|
||||
return isReady(o, obj.GetArtifact())
|
||||
|
|
|
|||
7
main.go
7
main.go
|
|
@ -181,6 +181,12 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
watchConfigsPredicate, err := helper.GetWatchConfigsPredicate(watchOptions)
|
||||
if err != nil {
|
||||
setupLog.Error(err, "unable to configure watch configs label selector for controller")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var disableCacheFor []ctrlclient.Object
|
||||
shouldCache, err := features.Enabled(features.CacheSecretsAndConfigMaps)
|
||||
if err != nil {
|
||||
|
|
@ -317,6 +323,7 @@ func main() {
|
|||
DependencyRequeueInterval: requeueDependency,
|
||||
HTTPRetry: httpRetry,
|
||||
RateLimiter: helper.GetRateLimiter(rateLimiterOptions),
|
||||
WatchConfigsPredicate: watchConfigsPredicate,
|
||||
}); err != nil {
|
||||
setupLog.Error(err, "unable to create controller", "controller", v2.HelmReleaseKind)
|
||||
os.Exit(1)
|
||||
|
|
|
|||
Loading…
Reference in New Issue