Skip to content

Commit 325f26f

Browse files
committed
feat: add FieldIgnore functionality
this is a cleaner API around ignoring certain fields in watches and when installing charts, through a PostRender func. The goal is to eventually expose this API to the user, but for now it'll just help to keep track of our default ignores that we have implemented to fix specific bugs. Signed-off-by: Daniel Grimm <dgrimm@redhat.com>
1 parent 37f2998 commit 325f26f

15 files changed

Lines changed: 1818 additions & 195 deletions

File tree

cmd/main.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/istio-ecosystem/sail-operator/controllers/ztunnel"
3131
"github.com/istio-ecosystem/sail-operator/pkg/config"
3232
"github.com/istio-ecosystem/sail-operator/pkg/enqueuelogger"
33+
"github.com/istio-ecosystem/sail-operator/pkg/fieldignore"
3334
"github.com/istio-ecosystem/sail-operator/pkg/helm"
3435
"github.com/istio-ecosystem/sail-operator/pkg/scheme"
3536
"github.com/istio-ecosystem/sail-operator/pkg/version"
@@ -202,7 +203,8 @@ func main() {
202203
os.Exit(1)
203204
}
204205

205-
chartManager := helm.NewChartManager(mgr.GetConfig(), os.Getenv("HELM_DRIVER"))
206+
chartManager := helm.NewChartManager(mgr.GetConfig(), os.Getenv("HELM_DRIVER"),
207+
helm.WithFieldIgnoreRules(fieldignore.IntoUntypedAll(fieldignore.DefaultRules)))
206208

207209
err = istio.NewReconciler(reconcilerCfg, mgr.GetClient(), mgr.GetScheme(), tlsConfig).
208210
SetupWithManager(mgr)

controllers/istiocni/istiocni_controller.go

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/istio-ecosystem/sail-operator/pkg/constants"
2626
"github.com/istio-ecosystem/sail-operator/pkg/enqueuelogger"
2727
"github.com/istio-ecosystem/sail-operator/pkg/errlist"
28+
"github.com/istio-ecosystem/sail-operator/pkg/fieldignore"
2829
"github.com/istio-ecosystem/sail-operator/pkg/helm"
2930
"github.com/istio-ecosystem/sail-operator/pkg/predicate"
3031
sharedreconcile "github.com/istio-ecosystem/sail-operator/pkg/reconcile"
@@ -161,26 +162,31 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
161162
Named("istiocni").
162163

163164
// namespaced resources
164-
Watches(&corev1.ConfigMap{}, ownedResourceHandler).
165-
Watches(&appsv1.DaemonSet{}, ownedResourceHandler).
166-
Watches(&corev1.ResourceQuota{}, ownedResourceHandler).
165+
Watches(&corev1.ConfigMap{}, ownedResourceHandler,
166+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &corev1.ConfigMap{}).NewPredicate())).
167+
Watches(&appsv1.DaemonSet{}, ownedResourceHandler,
168+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &appsv1.DaemonSet{}).NewPredicate())).
169+
Watches(&corev1.ResourceQuota{}, ownedResourceHandler,
170+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &corev1.ResourceQuota{}).NewPredicate())).
167171

168172
// +lint-watches:ignore: NetworkPolicy (FIXME: NetworkPolicy has not yet been added upstream, but is WIP)
169-
Watches(&networkingv1.NetworkPolicy{}, ownedResourceHandler, builder.WithPredicates(predicate.IgnoreUpdate())).
170-
171-
// We use predicate.IgnoreUpdate() so that we skip the reconciliation when a pull secret is added to the ServiceAccount.
172-
// This is necessary so that we don't remove the newly-added secret.
173-
// TODO: this is a temporary hack until we implement the correct solution on the Helm-render side
174-
Watches(&corev1.ServiceAccount{}, ownedResourceHandler, builder.WithPredicates(predicate.IgnoreUpdate())).
173+
Watches(&networkingv1.NetworkPolicy{}, ownedResourceHandler,
174+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &networkingv1.NetworkPolicy{}).NewPredicate(), predicate.IgnoreUpdate())).
175+
Watches(&corev1.ServiceAccount{}, ownedResourceHandler,
176+
builder.WithPredicates(
177+
fieldignore.RulesFor(fieldignore.DefaultRules, &corev1.ServiceAccount{}).NewPredicate(),
178+
predicate.IgnoreUpdateWhenAnnotation())).
175179

176180
// TODO: only register NetAttachDef if the CRD is installed (may also need to watch for CRD creation)
177181
// Owns(&multusv1.NetworkAttachmentDefinition{}).
178182

179183
// cluster-scoped resources
180184
// +lint-watches:ignore: Namespace (not present in charts, but must be watched to reconcile IstioCni when its namespace is created)
181185
Watches(&corev1.Namespace{}, namespaceHandler).
182-
Watches(&rbacv1.ClusterRole{}, ownedResourceHandler).
183-
Watches(&rbacv1.ClusterRoleBinding{}, ownedResourceHandler).
186+
Watches(&rbacv1.ClusterRole{}, ownedResourceHandler,
187+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &rbacv1.ClusterRole{}).NewPredicate())).
188+
Watches(&rbacv1.ClusterRoleBinding{}, ownedResourceHandler,
189+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &rbacv1.ClusterRoleBinding{}).NewPredicate())).
184190
Complete(reconciler.NewStandardReconcilerWithFinalizer[*v1.IstioCNI](r.Client, r.Reconcile, r.Finalize, constants.FinalizerName))
185191
}
186192

controllers/istiorevision/istiorevision_controller.go

Lines changed: 39 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/istio-ecosystem/sail-operator/pkg/constants"
2727
"github.com/istio-ecosystem/sail-operator/pkg/enqueuelogger"
2828
"github.com/istio-ecosystem/sail-operator/pkg/errlist"
29+
"github.com/istio-ecosystem/sail-operator/pkg/fieldignore"
2930
"github.com/istio-ecosystem/sail-operator/pkg/helm"
3031
predicate2 "github.com/istio-ecosystem/sail-operator/pkg/predicate"
3132
sharedreconcile "github.com/istio-ecosystem/sail-operator/pkg/reconcile"
@@ -274,29 +275,41 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
274275
Named("istiorevision").
275276

276277
// namespaced resources
277-
Watches(&corev1.ConfigMap{}, ownedResourceHandler, builder.WithPredicates(predicate2.IgnoreUpdateWhenAnnotation())).
278+
Watches(&corev1.ConfigMap{}, ownedResourceHandler,
279+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &corev1.ConfigMap{}).NewPredicate(), predicate2.IgnoreUpdateWhenAnnotation())).
278280
// We don't ignore the status for Deployments because we use it to calculate the IstioRevision status
279-
Watches(&appsv1.Deployment{}, ownedResourceHandler, builder.WithPredicates(predicate2.IgnoreUpdateWhenAnnotation())).
281+
Watches(&appsv1.Deployment{}, ownedResourceHandler,
282+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &appsv1.Deployment{}).NewPredicate(), predicate2.IgnoreUpdateWhenAnnotation())).
280283
// +lint-watches:ignore: Endpoints (older versions of istiod chart create Endpoints for remote installs, but this controller watches EndpointSlices)
281284
// +lint-watches:ignore: EndpointSlice (istiod chart creates Endpoints for remote installs, but this controller watches EndpointSlices)
282-
Watches(&discoveryv1.EndpointSlice{}, endpointSliceHandler, builder.WithPredicates(predicate2.IgnoreUpdateWhenAnnotation())).
285+
Watches(&discoveryv1.EndpointSlice{}, endpointSliceHandler,
286+
builder.WithPredicates(
287+
fieldignore.RulesFor(fieldignore.DefaultRules, &discoveryv1.EndpointSlice{}).NewPredicate(),
288+
predicate2.IgnoreUpdateWhenAnnotation())).
283289
Watches(&corev1.Service{}, ownedResourceHandler,
284-
builder.WithPredicates(ignoreStatusChange(), predicate2.IgnoreUpdateWhenAnnotation())).
290+
builder.WithPredicates(
291+
fieldignore.RulesFor(fieldignore.DefaultRules, &corev1.Service{}).NewPredicate(),
292+
ignoreStatusChange(), predicate2.IgnoreUpdateWhenAnnotation())).
285293

286294
// +lint-watches:ignore: NetworkPolicy (FIXME: NetworkPolicy has not yet been added upstream, but is WIP)
287295
Watches(&networkingv1.NetworkPolicy{}, ownedResourceHandler,
288-
builder.WithPredicates(ignoreStatusChange(), predicate2.IgnoreUpdateWhenAnnotation())).
289-
290-
// We use predicate.IgnoreUpdate() so that we skip the reconciliation when a pull secret is added to the ServiceAccount.
291-
// This is necessary so that we don't remove the newly-added secret.
292-
// TODO: this is a temporary hack until we implement the correct solution on the Helm-render side
293-
Watches(&corev1.ServiceAccount{}, ownedResourceHandler, builder.WithPredicates(predicate2.IgnoreUpdate())).
294-
Watches(&rbacv1.Role{}, ownedResourceHandler, builder.WithPredicates(predicate2.IgnoreUpdateWhenAnnotation())).
295-
Watches(&rbacv1.RoleBinding{}, ownedResourceHandler, builder.WithPredicates(predicate2.IgnoreUpdateWhenAnnotation())).
296+
builder.WithPredicates(
297+
fieldignore.RulesFor(fieldignore.DefaultRules, &networkingv1.NetworkPolicy{}).NewPredicate(),
298+
ignoreStatusChange(), predicate2.IgnoreUpdateWhenAnnotation())).
299+
Watches(&corev1.ServiceAccount{}, ownedResourceHandler,
300+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &corev1.ServiceAccount{}).NewPredicate(), predicate2.IgnoreUpdateWhenAnnotation())).
301+
Watches(&rbacv1.Role{}, ownedResourceHandler,
302+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &rbacv1.Role{}).NewPredicate(), predicate2.IgnoreUpdateWhenAnnotation())).
303+
Watches(&rbacv1.RoleBinding{}, ownedResourceHandler,
304+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &rbacv1.RoleBinding{}).NewPredicate(), predicate2.IgnoreUpdateWhenAnnotation())).
296305
Watches(&policyv1.PodDisruptionBudget{}, ownedResourceHandler,
297-
builder.WithPredicates(ignoreStatusChange(), predicate2.IgnoreUpdateWhenAnnotation())).
306+
builder.WithPredicates(
307+
fieldignore.RulesFor(fieldignore.DefaultRules, &policyv1.PodDisruptionBudget{}).NewPredicate(),
308+
ignoreStatusChange(), predicate2.IgnoreUpdateWhenAnnotation())).
298309
Watches(&autoscalingv2.HorizontalPodAutoscaler{}, ownedResourceHandler,
299-
builder.WithPredicates(ignoreStatusChange(), predicate2.IgnoreUpdateWhenAnnotation())).
310+
builder.WithPredicates(
311+
fieldignore.RulesFor(fieldignore.DefaultRules, &autoscalingv2.HorizontalPodAutoscaler{}).NewPredicate(),
312+
ignoreStatusChange(), predicate2.IgnoreUpdateWhenAnnotation())).
300313

301314
// +lint-watches:ignore: Namespace (not found in charts, but must be watched to reconcile IstioRevision when its namespace is created)
302315
Watches(&corev1.Namespace{}, nsHandler, builder.WithPredicates(ignoreStatusChange()), builder.WithPredicates(predicate2.IgnoreUpdateWhenAnnotation())).
@@ -308,12 +321,20 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
308321
Watches(&v1.IstioRevisionTag{}, revisionTagHandler).
309322

310323
// cluster-scoped resources
311-
Watches(&rbacv1.ClusterRole{}, ownedResourceHandler, builder.WithPredicates(predicate2.IgnoreUpdateWhenAnnotation())).
312-
Watches(&rbacv1.ClusterRoleBinding{}, ownedResourceHandler, builder.WithPredicates(predicate2.IgnoreUpdateWhenAnnotation())).
324+
Watches(&rbacv1.ClusterRole{}, ownedResourceHandler,
325+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &rbacv1.ClusterRole{}).NewPredicate(), predicate2.IgnoreUpdateWhenAnnotation())).
326+
Watches(&rbacv1.ClusterRoleBinding{}, ownedResourceHandler,
327+
builder.WithPredicates(
328+
fieldignore.RulesFor(fieldignore.DefaultRules, &rbacv1.ClusterRoleBinding{}).NewPredicate(),
329+
predicate2.IgnoreUpdateWhenAnnotation())).
313330
Watches(&admissionv1.MutatingWebhookConfiguration{}, ownedResourceHandler,
314-
builder.WithPredicates(webhookConfigPredicate(), predicate2.IgnoreUpdateWhenAnnotation())).
331+
builder.WithPredicates(
332+
fieldignore.RulesFor(fieldignore.DefaultRules, &admissionv1.MutatingWebhookConfiguration{}).NewPredicate(),
333+
predicate2.IgnoreUpdateWhenAnnotation())).
315334
Watches(&admissionv1.ValidatingWebhookConfiguration{}, ownedResourceHandler,
316-
builder.WithPredicates(webhookConfigPredicate(), predicate2.IgnoreUpdateWhenAnnotation())).
335+
builder.WithPredicates(
336+
fieldignore.RulesFor(fieldignore.DefaultRules, &admissionv1.ValidatingWebhookConfiguration{}).NewPredicate(),
337+
predicate2.IgnoreUpdateWhenAnnotation())).
317338

318339
// +lint-watches:ignore: IstioCNI (not found in charts, but this controller needs to watch it to update the IstioRevision status)
319340
Watches(&v1.IstioCNI{}, istioCniHandler).
@@ -725,42 +746,6 @@ func specWasUpdated(oldObject client.Object, newObject client.Object) bool {
725746
return oldObject.GetGeneration() != newObject.GetGeneration()
726747
}
727748

728-
func webhookConfigPredicate() predicate.Funcs {
729-
return predicate.Funcs{
730-
UpdateFunc: func(e event.TypedUpdateEvent[client.Object]) bool {
731-
if e.ObjectOld == nil || e.ObjectNew == nil {
732-
return false
733-
}
734-
735-
// Istiod updates the caBundle and failurePolicy fields in its webhook configs.
736-
// We must ignore changes to these fields to prevent an endless update loop.
737-
// We must use deep copies to avoid mutating the shared informer cache.
738-
oldCopy := e.ObjectOld.DeepCopyObject().(client.Object)
739-
newCopy := e.ObjectNew.DeepCopyObject().(client.Object)
740-
clearIgnoredFields(oldCopy)
741-
clearIgnoredFields(newCopy)
742-
return !reflect.DeepEqual(newCopy, oldCopy)
743-
},
744-
}
745-
}
746-
747-
func clearIgnoredFields(obj client.Object) {
748-
obj.SetResourceVersion("")
749-
obj.SetGeneration(0)
750-
obj.SetManagedFields(nil)
751-
switch webhookConfig := obj.(type) {
752-
case *admissionv1.ValidatingWebhookConfiguration:
753-
for i := range len(webhookConfig.Webhooks) {
754-
webhookConfig.Webhooks[i].FailurePolicy = nil
755-
webhookConfig.Webhooks[i].ClientConfig.CABundle = nil
756-
}
757-
case *admissionv1.MutatingWebhookConfiguration:
758-
for i := range len(webhookConfig.Webhooks) {
759-
webhookConfig.Webhooks[i].ClientConfig.CABundle = nil
760-
}
761-
}
762-
}
763-
764749
func wrapEventHandler(logger logr.Logger, handler handler.EventHandler) handler.EventHandler {
765750
return enqueuelogger.WrapIfNecessary(v1.IstioRevisionKind, logger, handler)
766751
}

controllers/istiorevisiontag/istiorevisiontag_controller.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/istio-ecosystem/sail-operator/pkg/constants"
2828
"github.com/istio-ecosystem/sail-operator/pkg/enqueuelogger"
2929
"github.com/istio-ecosystem/sail-operator/pkg/errlist"
30+
"github.com/istio-ecosystem/sail-operator/pkg/fieldignore"
3031
"github.com/istio-ecosystem/sail-operator/pkg/helm"
3132
"github.com/istio-ecosystem/sail-operator/pkg/reconciler"
3233
"github.com/istio-ecosystem/sail-operator/pkg/revision"
@@ -251,7 +252,8 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
251252
// cluster-scoped resources
252253
Watches(&v1.Istio{}, operatorResourcesHandler).
253254
Watches(&v1.IstioRevision{}, operatorResourcesHandler).
254-
Watches(&admissionv1.MutatingWebhookConfiguration{}, ownedResourceHandler).
255+
Watches(&admissionv1.MutatingWebhookConfiguration{}, ownedResourceHandler,
256+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &admissionv1.MutatingWebhookConfiguration{}).NewPredicate())).
255257
Complete(reconciler.NewStandardReconcilerWithFinalizer[*v1.IstioRevisionTag](r.Client, r.Reconcile, r.Finalize, constants.FinalizerName))
256258
}
257259

controllers/webhook/webhook_controller.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/istio-ecosystem/sail-operator/pkg/config"
3131
"github.com/istio-ecosystem/sail-operator/pkg/constants"
3232
"github.com/istio-ecosystem/sail-operator/pkg/enqueuelogger"
33+
"github.com/istio-ecosystem/sail-operator/pkg/fieldignore"
3334
"github.com/istio-ecosystem/sail-operator/pkg/reconciler"
3435
"github.com/istio-ecosystem/sail-operator/pkg/revision"
3536
admissionv1 "k8s.io/api/admissionregistration/v1"
@@ -189,7 +190,10 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
189190

190191
// we use the Watches function instead of For(), so that we can wrap the handler so that events that cause the object to be enqueued are logged
191192
// +lint-watches:ignore: IstioRevision (not found in charts, but this is the main resource watched by this controller)
192-
Watches(&admissionv1.MutatingWebhookConfiguration{}, objectHandler, builder.WithPredicates(ownedByRemoteIstioRevisionPredicate(mgr.GetClient()))).
193+
Watches(&admissionv1.MutatingWebhookConfiguration{}, objectHandler,
194+
builder.WithPredicates(
195+
fieldignore.RulesFor(fieldignore.DefaultRules, &admissionv1.MutatingWebhookConfiguration{}).NewPredicate(),
196+
ownedByRemoteIstioRevisionPredicate(mgr.GetClient()))).
193197
Named("mutatingwebhookconfiguration").
194198
Complete(reconciler.NewStandardReconciler[*admissionv1.MutatingWebhookConfiguration](r.Client, r.Reconcile))
195199
}

controllers/ztunnel/ztunnel_controller.go

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/istio-ecosystem/sail-operator/pkg/constants"
2727
"github.com/istio-ecosystem/sail-operator/pkg/enqueuelogger"
2828
"github.com/istio-ecosystem/sail-operator/pkg/errlist"
29+
"github.com/istio-ecosystem/sail-operator/pkg/fieldignore"
2930
"github.com/istio-ecosystem/sail-operator/pkg/helm"
3031
"github.com/istio-ecosystem/sail-operator/pkg/predicate"
3132
sharedreconcile "github.com/istio-ecosystem/sail-operator/pkg/reconcile"
@@ -184,20 +185,22 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
184185
Named("ztunnel").
185186

186187
// namespaced resources
187-
Watches(&corev1.ConfigMap{}, ownedResourceHandler).
188-
Watches(&appsv1.DaemonSet{}, ownedResourceHandler).
189-
Watches(&corev1.ResourceQuota{}, ownedResourceHandler).
190-
191-
// We use predicate.IgnoreUpdate() so that we skip the reconciliation when a pull secret is added to the ServiceAccount.
192-
// This is necessary so that we don't remove the newly-added secret.
193-
// TODO: this is a temporary hack until we implement the correct solution on the Helm-render side
194-
Watches(&corev1.ServiceAccount{}, ownedResourceHandler, builder.WithPredicates(predicate.IgnoreUpdate())).
188+
Watches(&corev1.ConfigMap{}, ownedResourceHandler,
189+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &corev1.ConfigMap{}).NewPredicate())).
190+
Watches(&appsv1.DaemonSet{}, ownedResourceHandler,
191+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &appsv1.DaemonSet{}).NewPredicate())).
192+
Watches(&corev1.ResourceQuota{}, ownedResourceHandler,
193+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &corev1.ResourceQuota{}).NewPredicate())).
194+
Watches(&corev1.ServiceAccount{}, ownedResourceHandler,
195+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &corev1.ServiceAccount{}).NewPredicate(), predicate.IgnoreUpdateWhenAnnotation())).
195196

196197
// cluster-scoped resources
197198
// +lint-watches:ignore: Namespace (not present in charts, but must be watched to reconcile ZTunnel when its namespace is created)
198199
Watches(&corev1.Namespace{}, namespaceHandler).
199-
Watches(&rbacv1.ClusterRole{}, ownedResourceHandler).
200-
Watches(&rbacv1.ClusterRoleBinding{}, ownedResourceHandler).
200+
Watches(&rbacv1.ClusterRole{}, ownedResourceHandler,
201+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &rbacv1.ClusterRole{}).NewPredicate())).
202+
Watches(&rbacv1.ClusterRoleBinding{}, ownedResourceHandler,
203+
builder.WithPredicates(fieldignore.RulesFor(fieldignore.DefaultRules, &rbacv1.ClusterRoleBinding{}).NewPredicate())).
201204
Watches(&v1.Istio{}, operatorResourcesHandler).
202205
Watches(&v1.IstioRevision{}, operatorResourcesHandler).
203206
Complete(reconciler.NewStandardReconcilerWithFinalizer[*v1.ZTunnel](r.Client, r.Reconcile, r.Finalize, constants.FinalizerName))

pkg/fieldignore/defaults.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright Istio Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package fieldignore
16+
17+
import (
18+
admissionv1 "k8s.io/api/admissionregistration/v1"
19+
corev1 "k8s.io/api/core/v1"
20+
)
21+
22+
// DefaultRules defines the default set of fields to ignore on resources managed
23+
// by the operator. These prevent reconciliation loops caused by other
24+
// controllers (e.g. istiod, pull-secret injectors, Azure admission enforcer)
25+
// updating fields that the operator also manages via Helm.
26+
//
27+
// Use RulesFor to extract typed rules for a specific resource type.
28+
var DefaultRules = []RuleSet{
29+
TypedRuleSet[*admissionv1.ValidatingWebhookConfiguration]{
30+
{Fields: []string{"webhooks[*].failurePolicy"}, Scope: IgnoreScopeReconcileAndUpgrade},
31+
{Fields: []string{"webhooks[*].clientConfig.caBundle"}},
32+
},
33+
TypedRuleSet[*admissionv1.MutatingWebhookConfiguration]{
34+
{Fields: []string{"webhooks[*].clientConfig.caBundle"}},
35+
// AKS manipulates MutatingWebhookConfigurations. See https://github.com/istio-ecosystem/sail-operator/issues/1148
36+
{Fields: []string{"webhooks[*].namespaceSelector.matchExpressions[key=kubernetes.azure.com/managedby]"}, Scope: IgnoreScopeReconcile},
37+
},
38+
TypedRuleSet[*corev1.ServiceAccount]{
39+
{Fields: []string{"imagePullSecrets"}},
40+
{Fields: []string{"automountServiceAccountToken"}},
41+
{Fields: []string{"secrets"}},
42+
},
43+
}

0 commit comments

Comments
 (0)