From 7d100bae2e2e1c11daa94e10bd7f78a9edc1a47c Mon Sep 17 00:00:00 2001 From: Roi Vazquez Date: Wed, 11 Oct 2023 15:03:15 +0200 Subject: [PATCH 1/2] Use go 1.20 --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index defd538..d3b856a 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/3scale-ops/basereconciler -go 1.19 +go 1.20 require ( github.com/davecgh/go-spew v1.1.1 From e048e9740f489c970f0bddb318cb81585fcd0837 Mon Sep 17 00:00:00 2001 From: Roi Vazquez Date: Wed, 11 Oct 2023 15:08:30 +0200 Subject: [PATCH 2/2] Add generic function to reconcile resource properties --- go.mod | 2 +- property/changeset.go | 47 ++++++++++ resources/configmap.go | 18 ++-- resources/deployment.go | 117 ++++--------------------- resources/external_secret.go | 18 ++-- resources/grafana_dashboard.go | 18 ++-- resources/hpa.go | 29 +++---- resources/pdb.go | 37 +++----- resources/pipeline.go | 60 +++---------- resources/pod_monitor.go | 18 ++-- resources/role.go | 23 ++--- resources/rolebinding.go | 30 ++----- resources/service_account.go | 16 ++-- resources/services.go | 30 ++----- resources/statefulset.go | 152 ++++----------------------------- resources/task.go | 78 ++++------------- 16 files changed, 185 insertions(+), 508 deletions(-) create mode 100644 property/changeset.go diff --git a/go.mod b/go.mod index d3b856a..731dd38 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/external-secrets/external-secrets v0.8.1 github.com/go-logr/logr v1.2.4 github.com/go-test/deep v1.1.0 + github.com/google/go-cmp v0.5.9 github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e github.com/grafana-operator/grafana-operator/v4 v4.10.0 github.com/onsi/ginkgo/v2 v2.9.1 @@ -43,7 +44,6 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic v0.6.9 // indirect - github.com/google/go-cmp v0.5.9 // indirect github.com/google/go-containerregistry v0.15.2 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20230309165930-d61513b1440d // indirect diff --git a/property/changeset.go b/property/changeset.go new file mode 100644 index 0000000..aa4cddb --- /dev/null +++ b/property/changeset.go @@ -0,0 +1,47 @@ +package property + +import ( + "github.com/go-logr/logr" + "github.com/google/go-cmp/cmp" + "k8s.io/apimachinery/pkg/api/equality" +) + +type ChangeSet[T any] struct { + path string + current *T + desired *T +} + +func NewChangeSet[T any](path string, current *T, desired *T) *ChangeSet[T] { + return &ChangeSet[T]{path: path, current: current, desired: desired} +} + +// EnsureDesired checks if two structs are equal. If they are not, current is overwriten +// with the value of desired. Bool flag is returned to indicate if the value of current was changed. +func (set *ChangeSet[T]) EnsureDesired(logger logr.Logger) bool { + + if equality.Semantic.DeepEqual(set.current, set.desired) { + return false + } + + logger.V(1).Info("differences detected", "path", set.path, "diff", cmp.Diff(set.current, set.desired)) + *set.current = *set.desired + return true +} + +type ReconcilableProperty interface { + EnsureDesired(logger logr.Logger) bool +} + +func EnsureDesired(logger logr.Logger, changeSets ...ReconcilableProperty) bool { + changed := false + + for _, set := range changeSets { + + if set.EnsureDesired(logger) { + changed = true + } + } + + return changed +} diff --git a/resources/configmap.go b/resources/configmap.go index b657a90..86d69b7 100644 --- a/resources/configmap.go +++ b/resources/configmap.go @@ -4,9 +4,9 @@ import ( "context" "fmt" + "github.com/3scale-ops/basereconciler/property" "github.com/3scale-ops/basereconciler/reconciler" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" @@ -69,17 +69,11 @@ func (cmt ConfigMapTemplate) ResourceReconciler(ctx context.Context, cl client.C return nil } - /* Reconcile metadata */ - if !equality.Semantic.DeepEqual(instance.GetLabels(), desired.GetLabels()) { - instance.ObjectMeta.Labels = desired.GetLabels() - needsUpdate = true - } - - /* Reconcile the data */ - if !equality.Semantic.DeepEqual(instance.Data, desired.Data) { - instance.Data = desired.Data - needsUpdate = true - } + /* Ensure the resource is in its desired state */ + needsUpdate = property.EnsureDesired(logger, + property.NewChangeSet[map[string]string]("metadata.labels", &instance.ObjectMeta.Labels, &desired.ObjectMeta.Labels), + property.NewChangeSet[map[string]string]("data", &instance.Data, &desired.Data), + ) if needsUpdate { err := cl.Update(ctx, instance) diff --git a/resources/deployment.go b/resources/deployment.go index b36b856..b4cb0b5 100644 --- a/resources/deployment.go +++ b/resources/deployment.go @@ -4,12 +4,13 @@ import ( "context" "fmt" + "github.com/3scale-ops/basereconciler/property" "github.com/3scale-ops/basereconciler/reconciler" "github.com/3scale-ops/basereconciler/util" - "github.com/go-test/deep" appsv1 "k8s.io/api/apps/v1" - "k8s.io/apimachinery/pkg/api/equality" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" @@ -81,101 +82,13 @@ func (dep DeploymentTemplate) ResourceReconciler(ctx context.Context, cl client. return nil } - /* Reconcile metadata */ - + /* Merge annotations */ desired.ObjectMeta.Annotations = util.MergeMaps( map[string]string{}, desired.GetAnnotations(), map[string]string{"deployment.kubernetes.io/revision": instance.GetAnnotations()["deployment.kubernetes.io/revision"]}, ) - if !equality.Semantic.DeepEqual(instance.GetAnnotations(), desired.GetAnnotations()) { - logger.Info("resource update required due to differences in metadata.annotations.") - logger.V(1).Info( - fmt.Sprintf("metadata.annotations differences: %s", - deep.Equal(instance.GetAnnotations(), desired.GetAnnotations())), - ) - instance.ObjectMeta.Annotations = desired.GetAnnotations() - needsUpdate = true - } - if !equality.Semantic.DeepEqual(instance.GetLabels(), desired.GetLabels()) { - logger.Info("resource update required due to differences in metadata.labels.") - logger.V(1).Info( - fmt.Sprintf("metadata.labels differences: %s", - deep.Equal(instance.GetLabels(), desired.GetLabels())), - ) - instance.ObjectMeta.Labels = desired.GetLabels() - needsUpdate = true - } - - /* Reconcile the MinReadySeconds */ - if !equality.Semantic.DeepEqual(instance.Spec.MinReadySeconds, desired.Spec.MinReadySeconds) { - logger.Info("resource update required due to differences in spec.minReadySeconds.") - logger.V(1).Info( - fmt.Sprintf("spec.minReadySeconds differences: %s", - deep.Equal(instance.Spec.MinReadySeconds, desired.Spec.MinReadySeconds)), - ) - instance.Spec.MinReadySeconds = desired.Spec.MinReadySeconds - needsUpdate = true - } - - /* Reconcile the Replicas */ - if !equality.Semantic.DeepEqual(instance.Spec.Replicas, desired.Spec.Replicas) { - logger.Info("resource update required due to differences in spec.replicas.") - logger.V(1).Info( - fmt.Sprintf("spec.replicas differences: %s", - deep.Equal(instance.Spec.Replicas, desired.Spec.Replicas)), - ) - instance.Spec.Replicas = desired.Spec.Replicas - needsUpdate = true - } - - /* Reconcile the Selector */ - if !equality.Semantic.DeepEqual(instance.Spec.Selector, desired.Spec.Selector) { - logger.Info("resource update required due to differences in spec.selector.") - logger.V(1).Info( - fmt.Sprintf("spec.selector differences: %s", - deep.Equal(instance.Spec.Selector, desired.Spec.Selector)), - ) - instance.Spec.Selector = desired.Spec.Selector - needsUpdate = true - } - - /* Reconcile the Strategy */ - if !equality.Semantic.DeepEqual(instance.Spec.Strategy, desired.Spec.Strategy) { - logger.Info("resource update required due to differences in spec.strategy.") - logger.V(1).Info( - fmt.Sprintf("spec.strategy differences: %s", - deep.Equal(instance.Spec.Strategy, desired.Spec.Strategy)), - ) - instance.Spec.Strategy = desired.Spec.Strategy - needsUpdate = true - } - - /* Reconcile the Template Labels */ - if !equality.Semantic.DeepEqual( - instance.Spec.Template.ObjectMeta.Labels, desired.Spec.Template.ObjectMeta.Labels) { - logger.Info("resource update required due to differences in spec.template.metadata.labels.") - logger.V(1).Info( - fmt.Sprintf("spec.template.metadata.labels differences: %s", - deep.Equal(instance.Spec.Template.ObjectMeta.Labels, desired.Spec.Template.ObjectMeta.Labels)), - ) - instance.Spec.Template.ObjectMeta.Labels = desired.Spec.Template.ObjectMeta.Labels - needsUpdate = true - } - - /* Reconcile the Template Annotations */ - if !equality.Semantic.DeepEqual( - instance.Spec.Template.ObjectMeta.Annotations, desired.Spec.Template.ObjectMeta.Annotations) { - logger.Info("resource update required due differences in spec.template.metadata.annotations.") - logger.V(1).Info( - fmt.Sprintf("spec.template.metadata.annotations differences: %s", - deep.Equal(instance.Spec.Template.ObjectMeta.Annotations, desired.Spec.Template.ObjectMeta.Annotations)), - ) - instance.Spec.Template.ObjectMeta.Annotations = desired.Spec.Template.ObjectMeta.Annotations - needsUpdate = true - } - /* Inherit some values usually defaulted by the cluster if not defined on the template */ if desired.Spec.Template.Spec.DNSPolicy == "" { desired.Spec.Template.Spec.DNSPolicy = instance.Spec.Template.Spec.DNSPolicy @@ -184,16 +97,18 @@ func (dep DeploymentTemplate) ResourceReconciler(ctx context.Context, cl client. desired.Spec.Template.Spec.SchedulerName = instance.Spec.Template.Spec.SchedulerName } - /* Reconcile the Template Spec */ - if !equality.Semantic.DeepEqual(instance.Spec.Template.Spec, desired.Spec.Template.Spec) { - logger.Info("resource update required due to differences in spec.template.spec.") - logger.V(1).Info( - fmt.Sprintf("spec.template.spec differences: %s", - deep.Equal(instance.Spec.Template.Spec, desired.Spec.Template.Spec)), - ) - instance.Spec.Template.Spec = desired.Spec.Template.Spec - needsUpdate = true - } + /* Ensure the resource is in its desired state */ + needsUpdate = property.EnsureDesired(logger, + property.NewChangeSet[map[string]string]("metadata.labels", &instance.ObjectMeta.Labels, &desired.ObjectMeta.Labels), + property.NewChangeSet[map[string]string]("metadata.annotations", &instance.ObjectMeta.Annotations, &desired.ObjectMeta.Annotations), + property.NewChangeSet[int32]("spec.minReadySeconds", &instance.Spec.MinReadySeconds, &desired.Spec.MinReadySeconds), + property.NewChangeSet[int32]("spec.replicas", instance.Spec.Replicas, desired.Spec.Replicas), + property.NewChangeSet[metav1.LabelSelector]("spec.selector", instance.Spec.Selector, desired.Spec.Selector), + property.NewChangeSet[appsv1.DeploymentStrategy]("spec.strategy", &instance.Spec.Strategy, &desired.Spec.Strategy), + property.NewChangeSet[map[string]string]("spec.template.metadata.labels", &instance.Spec.Template.ObjectMeta.Labels, &desired.Spec.Template.ObjectMeta.Labels), + property.NewChangeSet[map[string]string]("spec.template.metadata.annotations", &instance.Spec.Template.ObjectMeta.Annotations, &desired.Spec.Template.ObjectMeta.Annotations), + property.NewChangeSet[corev1.PodSpec]("spec.template.spec", &instance.Spec.Template.Spec, &desired.Spec.Template.Spec), + ) if needsUpdate { err := cl.Update(ctx, instance) diff --git a/resources/external_secret.go b/resources/external_secret.go index 32d15b0..20c8c72 100644 --- a/resources/external_secret.go +++ b/resources/external_secret.go @@ -4,9 +4,9 @@ import ( "context" "fmt" + "github.com/3scale-ops/basereconciler/property" "github.com/3scale-ops/basereconciler/reconciler" externalsecretsv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" - "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" @@ -69,17 +69,11 @@ func (est ExternalSecretTemplate) ResourceReconciler(ctx context.Context, cl cli return nil } - /* Reconcile metadata */ - if !equality.Semantic.DeepEqual(instance.GetLabels(), desired.GetLabels()) { - instance.ObjectMeta.Labels = desired.GetLabels() - needsUpdate = true - } - - /* Reconcile the spec */ - if !equality.Semantic.DeepEqual(instance.Spec, desired.Spec) { - instance.Spec = desired.Spec - needsUpdate = true - } + /* Ensure the resource is in its desired state */ + needsUpdate = property.EnsureDesired(logger, + property.NewChangeSet[map[string]string]("metadata.labels", &instance.ObjectMeta.Labels, &desired.ObjectMeta.Labels), + property.NewChangeSet[externalsecretsv1beta1.ExternalSecretSpec]("spec", &instance.Spec, &desired.Spec), + ) if needsUpdate { err := cl.Update(ctx, instance) diff --git a/resources/grafana_dashboard.go b/resources/grafana_dashboard.go index 44990e4..59b761b 100644 --- a/resources/grafana_dashboard.go +++ b/resources/grafana_dashboard.go @@ -4,9 +4,9 @@ import ( "context" "fmt" + "github.com/3scale-ops/basereconciler/property" "github.com/3scale-ops/basereconciler/reconciler" grafanav1alpha1 "github.com/grafana-operator/grafana-operator/v4/api/integreatly/v1alpha1" - "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" @@ -69,17 +69,11 @@ func (gdt GrafanaDashboardTemplate) ResourceReconciler(ctx context.Context, cl c return nil } - /* Reconcile metadata */ - if !equality.Semantic.DeepEqual(instance.GetLabels(), desired.GetLabels()) { - instance.ObjectMeta.Labels = desired.GetLabels() - needsUpdate = true - } - - /* Reconcile the spec */ - if !equality.Semantic.DeepEqual(instance.Spec, desired.Spec) { - instance.Spec = desired.Spec - needsUpdate = true - } + /* Ensure the resource is in its desired state */ + needsUpdate = property.EnsureDesired(logger, + property.NewChangeSet[map[string]string]("metadata.labels", &instance.ObjectMeta.Labels, &desired.ObjectMeta.Labels), + property.NewChangeSet[grafanav1alpha1.GrafanaDashboardSpec]("spec", &instance.Spec, &desired.Spec), + ) if needsUpdate { err := cl.Update(ctx, instance) diff --git a/resources/hpa.go b/resources/hpa.go index 326fdd7..852346f 100644 --- a/resources/hpa.go +++ b/resources/hpa.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/3scale-ops/basereconciler/property" "github.com/3scale-ops/basereconciler/reconciler" autoscalingv2 "k8s.io/api/autoscaling/v2" "k8s.io/apimachinery/pkg/api/equality" @@ -79,25 +80,15 @@ func (hpat HorizontalPodAutoscalerTemplate) ResourceReconciler(ctx context.Conte needsUpdate = true } - /* Reconcile the ScaleTargetRef, MinReplicas, MaxReplicas and Metrics properties */ - if !equality.Semantic.DeepEqual(instance.Spec.ScaleTargetRef, desired.Spec.ScaleTargetRef) { - instance.Spec.ScaleTargetRef = desired.Spec.ScaleTargetRef - needsUpdate = true - } - - if !equality.Semantic.DeepEqual(instance.Spec.MinReplicas, desired.Spec.MinReplicas) { - instance.Spec.MinReplicas = desired.Spec.MinReplicas - needsUpdate = true - } - if !equality.Semantic.DeepEqual(instance.Spec.MaxReplicas, desired.Spec.MaxReplicas) { - instance.Spec.MaxReplicas = desired.Spec.MaxReplicas - needsUpdate = true - } - - if !equality.Semantic.DeepEqual(instance.Spec.Metrics, desired.Spec.Metrics) { - instance.Spec.Metrics = desired.Spec.Metrics - needsUpdate = true - } + /* Ensure the resource is in its desired state */ + needsUpdate = property.EnsureDesired(logger, + property.NewChangeSet[map[string]string]("metadata.labels", &instance.ObjectMeta.Labels, &desired.ObjectMeta.Labels), + property.NewChangeSet[map[string]string]("metadata.annotations", &instance.ObjectMeta.Annotations, &desired.ObjectMeta.Annotations), + property.NewChangeSet[autoscalingv2.CrossVersionObjectReference]("spec.scaleTargetRef", &instance.Spec.ScaleTargetRef, &desired.Spec.ScaleTargetRef), + property.NewChangeSet[int32]("spec.minReplicas", instance.Spec.MinReplicas, desired.Spec.MinReplicas), + property.NewChangeSet[int32]("spec.maxReplicas", &instance.Spec.MaxReplicas, &desired.Spec.MaxReplicas), + property.NewChangeSet[[]autoscalingv2.MetricSpec]("spec.metrics", &instance.Spec.Metrics, &desired.Spec.Metrics), + ) if needsUpdate { err := cl.Update(ctx, instance) diff --git a/resources/pdb.go b/resources/pdb.go index 57b094c..0493b2d 100644 --- a/resources/pdb.go +++ b/resources/pdb.go @@ -4,11 +4,13 @@ import ( "context" "fmt" + "github.com/3scale-ops/basereconciler/property" "github.com/3scale-ops/basereconciler/reconciler" policyv1 "k8s.io/api/policy/v1" - "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/intstr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" ) @@ -69,31 +71,14 @@ func (pdbt PodDisruptionBudgetTemplate) ResourceReconciler(ctx context.Context, return nil } - /* Reconcile metadata */ - if !equality.Semantic.DeepEqual(instance.GetAnnotations(), desired.GetAnnotations()) { - instance.ObjectMeta.Annotations = desired.GetAnnotations() - needsUpdate = true - } - if !equality.Semantic.DeepEqual(instance.GetLabels(), desired.GetLabels()) { - instance.ObjectMeta.Labels = desired.GetLabels() - needsUpdate = true - } - - /* Reconcile the maxUnavaliable and minAvaliable properties */ - if !equality.Semantic.DeepEqual(instance.Spec.MaxUnavailable, desired.Spec.MaxUnavailable) { - instance.Spec.MaxUnavailable = desired.Spec.MaxUnavailable - needsUpdate = true - } - if !equality.Semantic.DeepEqual(instance.Spec.MinAvailable, desired.Spec.MinAvailable) { - instance.Spec.MinAvailable = desired.Spec.MinAvailable - needsUpdate = true - } - - /* Reconcile label selector */ - if !equality.Semantic.DeepEqual(instance.Spec.Selector, desired.Spec.Selector) { - instance.Spec.Selector = desired.Spec.Selector - needsUpdate = true - } + /* Ensure the resource is in its desired state */ + needsUpdate = property.EnsureDesired(logger, + property.NewChangeSet[map[string]string]("metadata.labels", &instance.ObjectMeta.Labels, &desired.ObjectMeta.Labels), + property.NewChangeSet[map[string]string]("metadata.annotations", &instance.ObjectMeta.Annotations, &desired.ObjectMeta.Annotations), + property.NewChangeSet[intstr.IntOrString]("spec.maxUnavailable", instance.Spec.MaxUnavailable, desired.Spec.MaxUnavailable), + property.NewChangeSet[intstr.IntOrString]("spec.minAvailable", instance.Spec.MinAvailable, desired.Spec.MinAvailable), + property.NewChangeSet[metav1.LabelSelector]("spec.selector", instance.Spec.Selector, desired.Spec.Selector), + ) if needsUpdate { err := cl.Update(ctx, instance) diff --git a/resources/pipeline.go b/resources/pipeline.go index 81dbec5..f559a4a 100644 --- a/resources/pipeline.go +++ b/resources/pipeline.go @@ -4,9 +4,9 @@ import ( "context" "fmt" + "github.com/3scale-ops/basereconciler/property" "github.com/3scale-ops/basereconciler/reconciler" pipelinev1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" - "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" @@ -69,52 +69,18 @@ func (pt PipelineTemplate) ResourceReconciler(ctx context.Context, cl client.Cli return nil } - /* Reconcile metadata */ - if !equality.Semantic.DeepEqual(instance.GetLabels(), desired.GetLabels()) { - instance.ObjectMeta.Labels = desired.GetLabels() - needsUpdate = true - } - if !equality.Semantic.DeepEqual(instance.GetAnnotations(), desired.GetAnnotations()) { - instance.ObjectMeta.Annotations = desired.GetAnnotations() - needsUpdate = true - } - - /* Reconcile spec */ - - if instance.Spec.DisplayName != desired.Spec.DisplayName { - instance.Spec.DisplayName = desired.Spec.DisplayName - needsUpdate = true - } - - if instance.Spec.Description != desired.Spec.Description { - instance.Spec.Description = desired.Spec.Description - needsUpdate = true - } - - if !equality.Semantic.DeepEqual(instance.Spec.Params, desired.Spec.Params) { - instance.Spec.Params = desired.Spec.Params - needsUpdate = true - } - - if !equality.Semantic.DeepEqual(instance.Spec.Tasks, desired.Spec.Tasks) { - instance.Spec.Tasks = desired.Spec.Tasks - needsUpdate = true - } - - if !equality.Semantic.DeepEqual(instance.Spec.Workspaces, desired.Spec.Workspaces) { - instance.Spec.Workspaces = desired.Spec.Workspaces - needsUpdate = true - } - - if !equality.Semantic.DeepEqual(instance.Spec.Results, desired.Spec.Results) { - instance.Spec.Results = desired.Spec.Results - needsUpdate = true - } - - if !equality.Semantic.DeepEqual(instance.Spec.Finally, desired.Spec.Finally) { - instance.Spec.Finally = desired.Spec.Finally - needsUpdate = true - } + /* Ensure the resource is in its desired state */ + needsUpdate = property.EnsureDesired(logger, + property.NewChangeSet[map[string]string]("metadata.labels", &instance.ObjectMeta.Labels, &desired.ObjectMeta.Labels), + property.NewChangeSet[map[string]string]("metadata.annotations", &instance.ObjectMeta.Annotations, &desired.ObjectMeta.Annotations), + property.NewChangeSet[string]("spec.displayName", &instance.Spec.DisplayName, &desired.Spec.DisplayName), + property.NewChangeSet[string]("spec.description", &instance.Spec.Description, &desired.Spec.Description), + property.NewChangeSet[pipelinev1beta1.ParamSpecs]("spec.params", &instance.Spec.Params, &desired.Spec.Params), + property.NewChangeSet[[]pipelinev1beta1.PipelineTask]("spec.tasks", &instance.Spec.Tasks, &desired.Spec.Tasks), + property.NewChangeSet[[]pipelinev1beta1.PipelineWorkspaceDeclaration]("spec.workspaces", &instance.Spec.Workspaces, &desired.Spec.Workspaces), + property.NewChangeSet[[]pipelinev1beta1.PipelineResult]("spec.results", &instance.Spec.Results, &desired.Spec.Results), + property.NewChangeSet[[]pipelinev1beta1.PipelineTask]("spec.finally", &instance.Spec.Finally, &desired.Spec.Finally), + ) if needsUpdate { err := cl.Update(ctx, instance) diff --git a/resources/pod_monitor.go b/resources/pod_monitor.go index 9cae9e4..c689187 100644 --- a/resources/pod_monitor.go +++ b/resources/pod_monitor.go @@ -4,9 +4,9 @@ import ( "context" "fmt" + "github.com/3scale-ops/basereconciler/property" "github.com/3scale-ops/basereconciler/reconciler" monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" - "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" @@ -69,17 +69,11 @@ func (pmt PodMonitorTemplate) ResourceReconciler(ctx context.Context, cl client. return nil } - /* Reconcile metadata */ - if !equality.Semantic.DeepEqual(instance.GetLabels(), desired.GetLabels()) { - instance.ObjectMeta.Labels = desired.GetLabels() - needsUpdate = true - } - - /* Reconcile the spec */ - if !equality.Semantic.DeepEqual(instance.Spec, desired.Spec) { - instance.Spec = desired.Spec - needsUpdate = true - } + /* Ensure the resource is in its desired state */ + needsUpdate = property.EnsureDesired(logger, + property.NewChangeSet[map[string]string]("metadata.labels", &instance.ObjectMeta.Labels, &desired.ObjectMeta.Labels), + property.NewChangeSet[monitoringv1.PodMonitorSpec]("data", &instance.Spec, &desired.Spec), + ) if needsUpdate { err := cl.Update(ctx, instance) diff --git a/resources/role.go b/resources/role.go index 9a4012b..3ab9202 100644 --- a/resources/role.go +++ b/resources/role.go @@ -4,9 +4,9 @@ import ( "context" "fmt" + "github.com/3scale-ops/basereconciler/property" "github.com/3scale-ops/basereconciler/reconciler" rbacv1 "k8s.io/api/rbac/v1" - "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" @@ -69,21 +69,12 @@ func (rt RoleTemplate) ResourceReconciler(ctx context.Context, cl client.Client, return nil } - /* Reconcile metadata */ - if !equality.Semantic.DeepEqual(instance.GetLabels(), desired.GetLabels()) { - instance.ObjectMeta.Labels = desired.GetLabels() - needsUpdate = true - } - if !equality.Semantic.DeepEqual(instance.GetAnnotations(), desired.GetAnnotations()) { - instance.ObjectMeta.Annotations = desired.GetAnnotations() - needsUpdate = true - } - - /* Reconcile the rules */ - if !equality.Semantic.DeepEqual(instance.Rules, desired.Rules) { - instance.Rules = desired.Rules - needsUpdate = true - } + /* Ensure the resource is in its desired state */ + needsUpdate = property.EnsureDesired(logger, + property.NewChangeSet[map[string]string]("metadata.labels", &instance.ObjectMeta.Labels, &desired.ObjectMeta.Labels), + property.NewChangeSet[map[string]string]("metadata.annotations", &instance.ObjectMeta.Annotations, &desired.ObjectMeta.Annotations), + property.NewChangeSet[[]rbacv1.PolicyRule]("rules", &instance.Rules, &desired.Rules), + ) if needsUpdate { err := cl.Update(ctx, instance) diff --git a/resources/rolebinding.go b/resources/rolebinding.go index e73e2e1..f1c39bf 100644 --- a/resources/rolebinding.go +++ b/resources/rolebinding.go @@ -4,9 +4,9 @@ import ( "context" "fmt" + "github.com/3scale-ops/basereconciler/property" "github.com/3scale-ops/basereconciler/reconciler" rbacv1 "k8s.io/api/rbac/v1" - "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" @@ -69,27 +69,13 @@ func (rbt RoleBindingTemplate) ResourceReconciler(ctx context.Context, cl client return nil } - /* Reconcile metadata */ - if !equality.Semantic.DeepEqual(instance.GetLabels(), desired.GetLabels()) { - instance.ObjectMeta.Labels = desired.GetLabels() - needsUpdate = true - } - if !equality.Semantic.DeepEqual(instance.GetAnnotations(), desired.GetAnnotations()) { - instance.ObjectMeta.Annotations = desired.GetAnnotations() - needsUpdate = true - } - - /* Reconcile the roleref */ - if !equality.Semantic.DeepEqual(instance.RoleRef, desired.RoleRef) { - instance.RoleRef = desired.RoleRef - needsUpdate = true - } - - /* Reconcile the subjects */ - if !equality.Semantic.DeepEqual(instance.Subjects, desired.Subjects) { - instance.Subjects = desired.Subjects - needsUpdate = true - } + /* Ensure the resource is in its desired state */ + needsUpdate = property.EnsureDesired(logger, + property.NewChangeSet[map[string]string]("metadata.labels", &instance.ObjectMeta.Labels, &desired.ObjectMeta.Labels), + property.NewChangeSet[map[string]string]("metadata.annotations", &instance.ObjectMeta.Annotations, &desired.ObjectMeta.Annotations), + property.NewChangeSet[rbacv1.RoleRef]("roleRef", &instance.RoleRef, &desired.RoleRef), + property.NewChangeSet[[]rbacv1.Subject]("subjects", &instance.Subjects, &desired.Subjects), + ) if needsUpdate { err := cl.Update(ctx, instance) diff --git a/resources/service_account.go b/resources/service_account.go index ab6e0be..237bfe4 100644 --- a/resources/service_account.go +++ b/resources/service_account.go @@ -4,9 +4,9 @@ import ( "context" "fmt" + "github.com/3scale-ops/basereconciler/property" "github.com/3scale-ops/basereconciler/reconciler" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" @@ -69,15 +69,11 @@ func (sat ServiceAccountTemplate) ResourceReconciler(ctx context.Context, cl cli return nil } - /* Reconcile metadata */ - if !equality.Semantic.DeepEqual(instance.GetLabels(), desired.GetLabels()) { - instance.ObjectMeta.Labels = desired.GetLabels() - needsUpdate = true - } - if !equality.Semantic.DeepEqual(instance.GetAnnotations(), desired.GetAnnotations()) { - instance.ObjectMeta.Annotations = desired.GetAnnotations() - needsUpdate = true - } + /* Ensure the resource is in its desired state */ + needsUpdate = property.EnsureDesired(logger, + property.NewChangeSet[map[string]string]("metadata.labels", &instance.ObjectMeta.Labels, &desired.ObjectMeta.Labels), + property.NewChangeSet[map[string]string]("metadata.annotations", &instance.ObjectMeta.Annotations, &desired.ObjectMeta.Annotations), + ) if needsUpdate { err := cl.Update(ctx, instance) diff --git a/resources/services.go b/resources/services.go index 837b672..0c4a575 100644 --- a/resources/services.go +++ b/resources/services.go @@ -4,9 +4,9 @@ import ( "context" "fmt" + "github.com/3scale-ops/basereconciler/property" "github.com/3scale-ops/basereconciler/reconciler" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" @@ -59,27 +59,13 @@ func (st ServiceTemplate) ResourceReconciler(ctx context.Context, cl client.Clie return err } - /* Reconcile metadata */ - if !equality.Semantic.DeepEqual(instance.GetAnnotations(), desired.GetAnnotations()) { - instance.ObjectMeta.Annotations = desired.GetAnnotations() - needsUpdate = true - } - if !equality.Semantic.DeepEqual(instance.GetLabels(), desired.GetLabels()) { - instance.ObjectMeta.Labels = desired.GetLabels() - needsUpdate = true - } - - /* Reconcile the ports */ - if !equality.Semantic.DeepEqual(instance.Spec.Ports, desired.Spec.Ports) { - instance.Spec.Ports = desired.Spec.Ports - needsUpdate = true - } - - /* Reconcile label selector */ - if !equality.Semantic.DeepEqual(instance.Spec.Selector, desired.Spec.Selector) { - instance.Spec.Selector = desired.Spec.Selector - needsUpdate = true - } + /* Ensure the resource is in its desired state */ + needsUpdate = property.EnsureDesired(logger, + property.NewChangeSet[map[string]string]("metadata.labels", &instance.ObjectMeta.Labels, &desired.ObjectMeta.Labels), + property.NewChangeSet[map[string]string]("metadata.annotations", &instance.ObjectMeta.Annotations, &desired.ObjectMeta.Annotations), + property.NewChangeSet[[]corev1.ServicePort]("spec.ports", &instance.Spec.Ports, &desired.Spec.Ports), + property.NewChangeSet[map[string]string]("spec.selector", &instance.Spec.Selector, &desired.Spec.Selector), + ) if needsUpdate { err := cl.Update(ctx, instance) diff --git a/resources/statefulset.go b/resources/statefulset.go index 22edd70..c654270 100644 --- a/resources/statefulset.go +++ b/resources/statefulset.go @@ -4,11 +4,12 @@ import ( "context" "fmt" + "github.com/3scale-ops/basereconciler/property" "github.com/3scale-ops/basereconciler/reconciler" - "github.com/go-test/deep" appsv1 "k8s.io/api/apps/v1" - "k8s.io/apimachinery/pkg/api/equality" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" @@ -75,107 +76,6 @@ func (sts StatefulSetTemplate) ResourceReconciler(ctx context.Context, cl client return nil } - /* Reconcile metadata */ - if !equality.Semantic.DeepEqual(instance.GetAnnotations(), desired.GetAnnotations()) { - logger.Info("resource update required due to differences in metadata.annotations.") - logger.V(1).Info( - fmt.Sprintf("metadata.annotations differences: %s", - deep.Equal(instance.GetAnnotations(), desired.GetAnnotations())), - ) - instance.ObjectMeta.Annotations = desired.GetAnnotations() - needsUpdate = true - } - if !equality.Semantic.DeepEqual(instance.GetLabels(), desired.GetLabels()) { - logger.Info("resource update required due to differences in metadata.labels.") - logger.V(1).Info( - fmt.Sprintf("metadala.labels differences: %s", - deep.Equal(instance.GetLabels(), desired.GetLabels())), - ) - instance.ObjectMeta.Labels = desired.GetLabels() - needsUpdate = true - } - - /* Reconcile the MinReadySeconds */ - if !equality.Semantic.DeepEqual(instance.Spec.MinReadySeconds, desired.Spec.MinReadySeconds) { - logger.Info("resource update required due to differences in spec.minReadySeconds.") - logger.V(1).Info( - fmt.Sprintf("spec.minReadySeconds differences: %s", - deep.Equal(instance.Spec.MinReadySeconds, desired.Spec.MinReadySeconds)), - ) - instance.Spec.MinReadySeconds = desired.Spec.MinReadySeconds - needsUpdate = true - } - - /* Reconcile the PersistentVolumeClaimRetentionPolicy */ - if !equality.Semantic.DeepEqual(instance.Spec.PersistentVolumeClaimRetentionPolicy, desired.Spec.PersistentVolumeClaimRetentionPolicy) { - logger.Info("resource update required due to differences in spec.persistentVolumeClaimRetentionPolicy.") - logger.V(1).Info( - fmt.Sprintf("spec.persistentVolumeClaimRetentionPolicy differences: %s", - deep.Equal(instance.Spec.PersistentVolumeClaimRetentionPolicy, desired.Spec.PersistentVolumeClaimRetentionPolicy)), - ) - instance.Spec.PersistentVolumeClaimRetentionPolicy = desired.Spec.PersistentVolumeClaimRetentionPolicy - needsUpdate = true - } - - /* Reconcile the Replicas */ - if !equality.Semantic.DeepEqual(instance.Spec.Replicas, desired.Spec.Replicas) { - logger.Info("resource update required due to differences in spec.replicas.") - logger.V(1).Info( - fmt.Sprintf("spec.replicas differences: %s", - deep.Equal(instance.Spec.Replicas, desired.Spec.Replicas)), - ) - instance.Spec.Replicas = desired.Spec.Replicas - needsUpdate = true - } - - /* Reconcile the Selector */ - if !equality.Semantic.DeepEqual(instance.Spec.Selector, desired.Spec.Selector) { - logger.Info("resource update required due to differences in spec.selector.") - logger.V(1).Info( - fmt.Sprintf("spec.selector differences: %s", - deep.Equal(instance.Spec.Selector, desired.Spec.Selector)), - ) - instance.Spec.Selector = desired.Spec.Selector - needsUpdate = true - } - - /* Reconcile the ServiceName */ - if !equality.Semantic.DeepEqual(instance.Spec.ServiceName, desired.Spec.ServiceName) { - logger.Info("resource update required due to differences in spec.serviceName.") - logger.V(1).Info( - fmt.Sprintf("spec.serviceName differences: %s", - deep.Equal(instance.Spec.ServiceName, desired.Spec.ServiceName)), - ) - instance.Spec.ServiceName = desired.Spec.ServiceName - needsUpdate = true - } - - /* Reconcile the Template Labels */ - if !equality.Semantic.DeepEqual( - instance.Spec.Template.ObjectMeta.Labels, desired.Spec.Template.ObjectMeta.Labels) { - logger.Info("resource update required due to differences in spec.template.metadata.labels.") - logger.V(1).Info( - fmt.Sprintf("spec.template.metadata.labels differences: %s", - deep.Equal(instance.Spec.Template.ObjectMeta.Labels, desired.Spec.Template.ObjectMeta.Labels)), - ) - instance.Spec.Template.ObjectMeta.Labels = desired.Spec.Template.ObjectMeta.Labels - needsUpdate = true - } - - /* Reconcile the Template Annotations */ - if !equality.Semantic.DeepEqual( - instance.Spec.Template.ObjectMeta.Annotations, desired.Spec.Template.ObjectMeta.Annotations) { - logger.Info("resource update required due differences in spec.template.metadata.annotations.") - logger.V(1).Info( - fmt.Sprintf("spec.template.metadata.annotations differences: %s", - deep.Equal(instance.Spec.Template.ObjectMeta.Annotations, desired.Spec.Template.ObjectMeta.Annotations)), - ) - instance.Spec.Template.ObjectMeta.Annotations = desired.Spec.Template.ObjectMeta.Annotations - needsUpdate = true - } - - /* Reconcile the Template Spec */ - if desired.Spec.Template.Spec.SchedulerName == "" { desired.Spec.Template.Spec.SchedulerName = instance.Spec.Template.Spec.SchedulerName } @@ -183,37 +83,21 @@ func (sts StatefulSetTemplate) ResourceReconciler(ctx context.Context, cl client desired.Spec.Template.Spec.DNSPolicy = instance.Spec.Template.Spec.DNSPolicy } - if !equality.Semantic.DeepEqual(instance.Spec.Template.Spec, desired.Spec.Template.Spec) { - logger.Info("resource update required due to differences in spec.template.spec.") - logger.V(1).Info( - fmt.Sprintf("spec.template.spec differences: %s", - deep.Equal(instance.Spec.Template.Spec, desired.Spec.Template.Spec)), - ) - instance.Spec.Template.Spec = desired.Spec.Template.Spec - needsUpdate = true - } - - /* Reconcile the UpdateStrategy */ - if !equality.Semantic.DeepEqual(instance.Spec.UpdateStrategy, desired.Spec.UpdateStrategy) { - logger.Info("resource update required due to differences in spec.updateStrategy.") - logger.V(1).Info( - fmt.Sprintf("spec.updateStrategy differences: %s", - deep.Equal(instance.Spec.UpdateStrategy, desired.Spec.UpdateStrategy)), - ) - instance.Spec.UpdateStrategy = desired.Spec.UpdateStrategy - needsUpdate = true - } - - /* Reconcile the VolumeClaimTemplates */ - if !equality.Semantic.DeepEqual(instance.Spec.VolumeClaimTemplates, desired.Spec.VolumeClaimTemplates) { - logger.Info("resource update required due to differences in spec.volumeClaimTemplates.") - logger.V(1).Info( - fmt.Sprintf("spec.volumeClaimTemplates differences: %s", - deep.Equal(instance.Spec.VolumeClaimTemplates, desired.Spec.VolumeClaimTemplates)), - ) - instance.Spec.VolumeClaimTemplates = desired.Spec.VolumeClaimTemplates - needsUpdate = true - } + /* Ensure the resource is in its desired state */ + needsUpdate = property.EnsureDesired(logger, + property.NewChangeSet[map[string]string]("metadata.labels", &instance.ObjectMeta.Labels, &desired.ObjectMeta.Labels), + property.NewChangeSet[map[string]string]("metadata.annotations", &instance.ObjectMeta.Annotations, &desired.ObjectMeta.Annotations), + property.NewChangeSet[int32]("spec.minReadySeconds", &instance.Spec.MinReadySeconds, &desired.Spec.MinReadySeconds), + property.NewChangeSet[appsv1.StatefulSetPersistentVolumeClaimRetentionPolicy]("spec.persistentVolumeClaimRetentionPolicy", instance.Spec.PersistentVolumeClaimRetentionPolicy, desired.Spec.PersistentVolumeClaimRetentionPolicy), + property.NewChangeSet[int32]("spec.replicas", instance.Spec.Replicas, desired.Spec.Replicas), + property.NewChangeSet[metav1.LabelSelector]("spec.selector", instance.Spec.Selector, desired.Spec.Selector), + property.NewChangeSet[string]("spec.serviceName", &instance.Spec.ServiceName, &desired.Spec.ServiceName), + property.NewChangeSet[appsv1.StatefulSetUpdateStrategy]("spec.updateStrategy", &instance.Spec.UpdateStrategy, &desired.Spec.UpdateStrategy), + property.NewChangeSet[[]corev1.PersistentVolumeClaim]("spec.volumeClaimTemplates", &instance.Spec.VolumeClaimTemplates, &desired.Spec.VolumeClaimTemplates), + property.NewChangeSet[map[string]string]("spec.template.metadata.labels", &instance.Spec.Template.ObjectMeta.Labels, &desired.Spec.Template.ObjectMeta.Labels), + property.NewChangeSet[map[string]string]("spec.template.metadata.annotations", &instance.Spec.Template.ObjectMeta.Annotations, &desired.Spec.Template.ObjectMeta.Annotations), + property.NewChangeSet[corev1.PodSpec]("spec.template.spec", &instance.Spec.Template.Spec, &desired.Spec.Template.Spec), + ) if needsUpdate { err := cl.Update(ctx, instance) diff --git a/resources/task.go b/resources/task.go index 49d9594..d60903f 100644 --- a/resources/task.go +++ b/resources/task.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/3scale-ops/basereconciler/property" "github.com/3scale-ops/basereconciler/reconciler" pipelinev1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" - "k8s.io/apimachinery/pkg/api/equality" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" @@ -69,67 +70,20 @@ func (tt TaskTemplate) ResourceReconciler(ctx context.Context, cl client.Client, return nil } - /* Reconcile metadata */ - if !equality.Semantic.DeepEqual(instance.GetLabels(), desired.GetLabels()) { - instance.ObjectMeta.Labels = desired.GetLabels() - needsUpdate = true - } - if !equality.Semantic.DeepEqual(instance.GetAnnotations(), desired.GetAnnotations()) { - instance.ObjectMeta.Annotations = desired.GetAnnotations() - needsUpdate = true - } - - /* Reconcile spec */ - - if instance.Spec.DisplayName != desired.Spec.DisplayName { - instance.Spec.DisplayName = desired.Spec.DisplayName - needsUpdate = true - } - - if instance.Spec.Description != desired.Spec.Description { - instance.Spec.Description = desired.Spec.Description - needsUpdate = true - } - - if !equality.Semantic.DeepEqual(instance.Spec.Params, desired.Spec.Params) { - instance.Spec.Params = desired.Spec.Params - needsUpdate = true - } - - if !equality.Semantic.DeepEqual(instance.Spec.Steps, desired.Spec.Steps) { - instance.Spec.Steps = desired.Spec.Steps - needsUpdate = true - } - - if !equality.Semantic.DeepEqual(instance.Spec.StepTemplate, desired.Spec.StepTemplate) { - instance.Spec.StepTemplate = desired.Spec.StepTemplate - needsUpdate = true - } - - if !equality.Semantic.DeepEqual(instance.Spec.Volumes, desired.Spec.Volumes) { - instance.Spec.Volumes = desired.Spec.Volumes - needsUpdate = true - } - - if !equality.Semantic.DeepEqual(instance.Spec.Sidecars, desired.Spec.Sidecars) { - instance.Spec.Sidecars = desired.Spec.Sidecars - needsUpdate = true - } - - if !equality.Semantic.DeepEqual(instance.Spec.Workspaces, desired.Spec.Workspaces) { - instance.Spec.Workspaces = desired.Spec.Workspaces - needsUpdate = true - } - - if !equality.Semantic.DeepEqual(instance.Spec.Volumes, desired.Spec.Volumes) { - instance.Spec.Volumes = desired.Spec.Volumes - needsUpdate = true - } - - if !equality.Semantic.DeepEqual(instance.Spec.Results, desired.Spec.Results) { - instance.Spec.Results = desired.Spec.Results - needsUpdate = true - } + /* Ensure the resource is in its desired state */ + needsUpdate = property.EnsureDesired(logger, + property.NewChangeSet[map[string]string]("metadata.labels", &instance.ObjectMeta.Labels, &desired.ObjectMeta.Labels), + property.NewChangeSet[map[string]string]("metadata.annotations", &instance.ObjectMeta.Annotations, &desired.ObjectMeta.Annotations), + property.NewChangeSet[string]("spec.displayName", &instance.Spec.DisplayName, &desired.Spec.DisplayName), + property.NewChangeSet[string]("spec.description", &instance.Spec.Description, &desired.Spec.Description), + property.NewChangeSet[pipelinev1beta1.ParamSpecs]("spec.params", &instance.Spec.Params, &desired.Spec.Params), + property.NewChangeSet[[]pipelinev1beta1.Step]("spec.steps", &instance.Spec.Steps, &desired.Spec.Steps), + property.NewChangeSet[pipelinev1beta1.StepTemplate]("spec.stepTemplate", instance.Spec.StepTemplate, desired.Spec.StepTemplate), + property.NewChangeSet[[]corev1.Volume]("spec.volumes", &instance.Spec.Volumes, &desired.Spec.Volumes), + property.NewChangeSet[[]pipelinev1beta1.Sidecar]("spec.sidecars", &instance.Spec.Sidecars, &desired.Spec.Sidecars), + property.NewChangeSet[[]pipelinev1beta1.WorkspaceDeclaration]("spec.workspaces", &instance.Spec.Workspaces, &desired.Spec.Workspaces), + property.NewChangeSet[[]pipelinev1beta1.TaskResult]("spec.results", &instance.Spec.Results, &desired.Spec.Results), + ) if needsUpdate { err := cl.Update(ctx, instance)