diff --git a/go.mod b/go.mod index 8e5e716707..6e0ed3ebe1 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/openshift/api v0.0.0-20211209135129-c58d9f695577 github.com/openshift/build-machinery-go v0.0.0-20211213093930-7e33a7eb4ce3 - github.com/openshift/library-go v0.0.0-20211220195323-eca2c467c492 + github.com/openshift/library-go v0.0.0-20220121154930-b7889002d63e github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.11.0 github.com/sirupsen/logrus v1.8.1 diff --git a/go.sum b/go.sum index 096468f74c..ea07797156 100644 --- a/go.sum +++ b/go.sum @@ -652,8 +652,8 @@ github.com/openshift/build-machinery-go v0.0.0-20210712174854-1bb7fd1518d3/go.mo github.com/openshift/build-machinery-go v0.0.0-20211213093930-7e33a7eb4ce3 h1:65oBhJYHzYK5VL0gF1eiYY37lLzyLZ47b9y5Kib1nf8= github.com/openshift/build-machinery-go v0.0.0-20211213093930-7e33a7eb4ce3/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE= github.com/openshift/client-go v0.0.0-20211209144617-7385dd6338e3/go.mod h1:cwhyki5lqBmrT0m8Im+9I7PGFaraOzcYPtEz93RcsGY= -github.com/openshift/library-go v0.0.0-20211220195323-eca2c467c492 h1:oj/rSQqVWVj6YJUydZwLz2frrJreiyI4oa9g/YPgMsM= -github.com/openshift/library-go v0.0.0-20211220195323-eca2c467c492/go.mod h1:4UQ9snU1vg53fyTpHQw3vLPiAxI8ub5xrc+y8KPQQFs= +github.com/openshift/library-go v0.0.0-20220121154930-b7889002d63e h1:XDK1ZB6Q1YmYkxfEkRq9z92yzinaJMf+vvjeELKj+2I= +github.com/openshift/library-go v0.0.0-20220121154930-b7889002d63e/go.mod h1:6AmNM4N4nHftckybV/U7bQW+5AvK5TW81ndSI6KEidw= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= diff --git a/pkg/operator/awspodidentity/controller.go b/pkg/operator/awspodidentity/controller.go index 5e66d09f93..a55c9e4832 100644 --- a/pkg/operator/awspodidentity/controller.go +++ b/pkg/operator/awspodidentity/controller.go @@ -4,21 +4,15 @@ import ( "context" "fmt" "os" - "strings" "time" log "github.com/sirupsen/logrus" - admissionregistrationv1 "k8s.io/api/admissionregistration/v1" corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" - admissionregistrationclientv1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1" - "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" @@ -32,8 +26,6 @@ import ( configv1 "github.com/openshift/api/config/v1" "github.com/openshift/library-go/pkg/operator/events" "github.com/openshift/library-go/pkg/operator/resource/resourceapply" - "github.com/openshift/library-go/pkg/operator/resource/resourcehelper" - "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" "github.com/openshift/library-go/pkg/operator/resource/resourceread" "github.com/openshift/cloud-credential-operator/pkg/assets/v410_00_assets" @@ -300,8 +292,8 @@ func (r *staticResourceReconciler) ReconcileResources(ctx context.Context) error } // "v4.1.0/aws-pod-identity-webhook/mutatingwebhook.yaml" - requestedMutatingWebhookConfiguration := ReadMutatingWebhookConfigurationV1OrDie(v410_00_assets.MustAsset("v4.1.0/aws-pod-identity-webhook/mutatingwebhook.yaml")) - _, modified, err = ApplyMutatingWebhookConfiguration(r.clientset.AdmissionregistrationV1(), r.eventRecorder, requestedMutatingWebhookConfiguration) + requestedMutatingWebhookConfiguration := resourceread.ReadMutatingWebhookConfigurationV1OrDie(v410_00_assets.MustAsset("v4.1.0/aws-pod-identity-webhook/mutatingwebhook.yaml")) + _, modified, err = resourceapply.ApplyMutatingWebhookConfigurationImproved(context.TODO(), r.clientset.AdmissionregistrationV1(), r.eventRecorder, requestedMutatingWebhookConfiguration, r.cache) if err != nil { r.logger.WithError(err).Error("error applying MutatingWebhookConfiguration") return err @@ -312,65 +304,6 @@ func (r *staticResourceReconciler) ReconcileResources(ctx context.Context) error return nil } -// TODO: add MutatingWebhookConfiguration helpers to library-go/operator/resource - -func ReadMutatingWebhookConfigurationV1OrDie(objBytes []byte) *admissionregistrationv1.MutatingWebhookConfiguration { - requiredObj, err := runtime.Decode(defaultCodecs.UniversalDecoder(admissionregistrationv1.SchemeGroupVersion), objBytes) - if err != nil { - panic(err) - } - return requiredObj.(*admissionregistrationv1.MutatingWebhookConfiguration) -} - -// ApplyMutatingWebhookConfiguration merges objectmeta, does not worry about anything else -func ApplyMutatingWebhookConfiguration(client admissionregistrationclientv1.MutatingWebhookConfigurationsGetter, recorder events.Recorder, required *admissionregistrationv1.MutatingWebhookConfiguration) (*admissionregistrationv1.MutatingWebhookConfiguration, bool, error) { - existing, err := client.MutatingWebhookConfigurations().Get(context.TODO(), required.Name, metav1.GetOptions{}) - if apierrors.IsNotFound(err) { - actual, err := client.MutatingWebhookConfigurations().Create(context.TODO(), required, metav1.CreateOptions{}) - reportCreateEvent(recorder, required, err) - return actual, true, err - } - if err != nil { - return nil, false, err - } - - modified := resourcemerge.BoolPtr(false) - existingCopy := existing.DeepCopy() - - resourcemerge.EnsureObjectMeta(modified, &existingCopy.ObjectMeta, required.ObjectMeta) - - // TODO: add deeper inspection of the existing resource to make sure it is what we require - - if !*modified { - return existingCopy, false, nil - } - - actual, err := client.MutatingWebhookConfigurations().Update(context.TODO(), existingCopy, metav1.UpdateOptions{}) - reportUpdateEvent(recorder, required, err) - return actual, true, err -} - -func reportCreateEvent(recorder events.Recorder, obj runtime.Object, originalErr error) { - gvk := resourcehelper.GuessObjectGroupVersionKind(obj) - if originalErr == nil { - recorder.Eventf(fmt.Sprintf("%sCreated", gvk.Kind), "Created %s because it was missing", resourcehelper.FormatResourceForCLI(obj)) - return - } - recorder.Warningf(fmt.Sprintf("%sCreateFailed", gvk.Kind), "Failed to create %s: %v", resourcehelper.FormatResourceForCLI(obj), originalErr) -} - -func reportUpdateEvent(recorder events.Recorder, obj runtime.Object, originalErr error, details ...string) { - gvk := resourcehelper.GuessObjectGroupVersionKind(obj) - switch { - case originalErr != nil: - recorder.Warningf(fmt.Sprintf("%sUpdateFailed", gvk.Kind), "Failed to update %s: %v", resourcehelper.FormatResourceForCLI(obj), originalErr) - case len(details) == 0: - recorder.Eventf(fmt.Sprintf("%sUpdated", gvk.Kind), "Updated %s because it changed", resourcehelper.FormatResourceForCLI(obj)) - default: - recorder.Eventf(fmt.Sprintf("%sUpdated", gvk.Kind), "Updated %s:\n%s", resourcehelper.FormatResourceForCLI(obj), strings.Join(details, "\n")) - } -} - var _ status.Handler = &staticResourceReconciler{} func (r *staticResourceReconciler) GetConditions(logger log.FieldLogger) ([]configv1.ClusterOperatorStatusCondition, error) { diff --git a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/admissionregistration.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/admissionregistration.go index 67b6a615d0..fafa39c404 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/admissionregistration.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/admissionregistration.go @@ -7,50 +7,60 @@ import ( "github.com/openshift/library-go/pkg/operator/events" "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" - admissionregistrationclientv1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1" - "k8s.io/klog/v2" - + "k8s.io/apimachinery/pkg/api/equality" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + admissionregistrationclientv1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1" + "k8s.io/klog/v2" ) -// ApplyMutatingWebhookConfiguration ensures the form of the specified +// ApplyMutatingWebhookConfigurationImproved ensures the form of the specified // mutatingwebhookconfiguration is present in the API. If it does not exist, // it will be created. If it does exist, the metadata of the required // mutatingwebhookconfiguration will be merged with the existing mutatingwebhookconfiguration // and an update performed if the mutatingwebhookconfiguration spec and metadata differ from // the previously required spec and metadata based on generation change. -func ApplyMutatingWebhookConfiguration(ctx context.Context, client admissionregistrationclientv1.MutatingWebhookConfigurationsGetter, recorder events.Recorder, - requiredOriginal *admissionregistrationv1.MutatingWebhookConfiguration) (*admissionregistrationv1.MutatingWebhookConfiguration, bool, error) { +func ApplyMutatingWebhookConfigurationImproved(ctx context.Context, client admissionregistrationclientv1.MutatingWebhookConfigurationsGetter, recorder events.Recorder, + requiredOriginal *admissionregistrationv1.MutatingWebhookConfiguration, cache ResourceCache) (*admissionregistrationv1.MutatingWebhookConfiguration, bool, error) { if requiredOriginal == nil { return nil, false, fmt.Errorf("Unexpected nil instead of an object") } - required := requiredOriginal.DeepCopy() - existing, err := client.MutatingWebhookConfigurations().Get(ctx, required.GetName(), metav1.GetOptions{}) + existing, err := client.MutatingWebhookConfigurations().Get(ctx, requiredOriginal.GetName(), metav1.GetOptions{}) if apierrors.IsNotFound(err) { + required := requiredOriginal.DeepCopy() actual, err := client.MutatingWebhookConfigurations().Create( ctx, resourcemerge.WithCleanLabelsAndAnnotations(required).(*admissionregistrationv1.MutatingWebhookConfiguration), metav1.CreateOptions{}) reportCreateEvent(recorder, required, err) if err != nil { return nil, false, err } + // need to store the original so that the early comparison of hashes is done based on the original, not a mutated copy + cache.UpdateCachedResourceMetadata(requiredOriginal, actual) return actual, true, nil } else if err != nil { return nil, false, err } + if cache.SafeToSkipApply(requiredOriginal, existing) { + return existing, false, nil + } + + required := requiredOriginal.DeepCopy() modified := resourcemerge.BoolPtr(false) existingCopy := existing.DeepCopy() resourcemerge.EnsureObjectMeta(modified, &existingCopy.ObjectMeta, required.ObjectMeta) - if !*modified { + copyMutatingWebhookCABundle(existing, required) + webhooksEquivalent := equality.Semantic.DeepEqual(existingCopy.Webhooks, required.Webhooks) + if webhooksEquivalent && !*modified { + // need to store the original so that the early comparison of hashes is done based on the original, not a mutated copy + cache.UpdateCachedResourceMetadata(requiredOriginal, existingCopy) return existingCopy, false, nil } // at this point we know that we're going to perform a write. We're just trying to get the object correct toWrite := existingCopy // shallow copy so the code reads easier - copyMutatingWebhookCABundle(existing, required) toWrite.Webhooks = required.Webhooks klog.V(4).Infof("MutatingWebhookConfiguration %q changes: %v", required.GetNamespace()+"/"+required.GetName(), JSONPatchNoError(existing, toWrite)) @@ -60,7 +70,9 @@ func ApplyMutatingWebhookConfiguration(ctx context.Context, client admissionregi if err != nil { return nil, false, err } - return actual, *modified || actual.GetGeneration() > existingCopy.GetGeneration(), nil + // need to store the original so that the early comparison of hashes is done based on the original, not a mutated copy + cache.UpdateCachedResourceMetadata(requiredOriginal, actual) + return actual, true, nil } // copyMutatingWebhookCABundle populates webhooks[].clientConfig.caBundle fields from existing resource if it was set before @@ -78,42 +90,52 @@ func copyMutatingWebhookCABundle(from, to *admissionregistrationv1.MutatingWebho } } -// ApplyValidatingWebhookConfiguration ensures the form of the specified +// ApplyValidatingWebhookConfigurationImproved ensures the form of the specified // validatingwebhookconfiguration is present in the API. If it does not exist, // it will be created. If it does exist, the metadata of the required // validatingwebhookconfiguration will be merged with the existing validatingwebhookconfiguration // and an update performed if the validatingwebhookconfiguration spec and metadata differ from // the previously required spec and metadata based on generation change. -func ApplyValidatingWebhookConfiguration(ctx context.Context, client admissionregistrationclientv1.ValidatingWebhookConfigurationsGetter, recorder events.Recorder, - requiredOriginal *admissionregistrationv1.ValidatingWebhookConfiguration) (*admissionregistrationv1.ValidatingWebhookConfiguration, bool, error) { +func ApplyValidatingWebhookConfigurationImproved(ctx context.Context, client admissionregistrationclientv1.ValidatingWebhookConfigurationsGetter, recorder events.Recorder, + requiredOriginal *admissionregistrationv1.ValidatingWebhookConfiguration, cache ResourceCache) (*admissionregistrationv1.ValidatingWebhookConfiguration, bool, error) { if requiredOriginal == nil { return nil, false, fmt.Errorf("Unexpected nil instead of an object") } - required := requiredOriginal.DeepCopy() - existing, err := client.ValidatingWebhookConfigurations().Get(ctx, required.GetName(), metav1.GetOptions{}) + existing, err := client.ValidatingWebhookConfigurations().Get(ctx, requiredOriginal.GetName(), metav1.GetOptions{}) if apierrors.IsNotFound(err) { + required := requiredOriginal.DeepCopy() actual, err := client.ValidatingWebhookConfigurations().Create( ctx, resourcemerge.WithCleanLabelsAndAnnotations(required).(*admissionregistrationv1.ValidatingWebhookConfiguration), metav1.CreateOptions{}) reportCreateEvent(recorder, required, err) if err != nil { return nil, false, err } + // need to store the original so that the early comparison of hashes is done based on the original, not a mutated copy + cache.UpdateCachedResourceMetadata(requiredOriginal, actual) return actual, true, nil } else if err != nil { return nil, false, err } + if cache.SafeToSkipApply(requiredOriginal, existing) { + return existing, false, nil + } + + required := requiredOriginal.DeepCopy() modified := resourcemerge.BoolPtr(false) existingCopy := existing.DeepCopy() resourcemerge.EnsureObjectMeta(modified, &existingCopy.ObjectMeta, required.ObjectMeta) - if !*modified { + copyValidatingWebhookCABundle(existing, required) + webhooksEquivalent := equality.Semantic.DeepEqual(existingCopy.Webhooks, required.Webhooks) + if webhooksEquivalent && !*modified { + // need to store the original so that the early comparison of hashes is done based on the original, not a mutated copy + cache.UpdateCachedResourceMetadata(requiredOriginal, existingCopy) return existingCopy, false, nil } // at this point we know that we're going to perform a write. We're just trying to get the object correct toWrite := existingCopy // shallow copy so the code reads easier - copyValidatingWebhookCABundle(existing, required) toWrite.Webhooks = required.Webhooks klog.V(4).Infof("ValidatingWebhookConfiguration %q changes: %v", required.GetNamespace()+"/"+required.GetName(), JSONPatchNoError(existing, toWrite)) @@ -123,7 +145,9 @@ func ApplyValidatingWebhookConfiguration(ctx context.Context, client admissionre if err != nil { return nil, false, err } - return actual, *modified || actual.GetGeneration() > existingCopy.GetGeneration(), nil + // need to store the original so that the early comparison of hashes is done based on the original, not a mutated copy + cache.UpdateCachedResourceMetadata(requiredOriginal, actual) + return actual, true, nil } // copyValidatingWebhookCABundle populates webhooks[].clientConfig.caBundle fields from existing resource if it was set before diff --git a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/generic.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/generic.go index c0a9fc8f4b..6f654250e4 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/generic.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/generic.go @@ -206,13 +206,13 @@ func ApplyDirectly(ctx context.Context, clients *ClientHolder, recorder events.R if clients.kubeClient == nil { result.Error = fmt.Errorf("missing kubeClient") } else { - result.Result, result.Changed, result.Error = ApplyValidatingWebhookConfiguration(ctx, clients.kubeClient.AdmissionregistrationV1(), recorder, t) + result.Result, result.Changed, result.Error = ApplyValidatingWebhookConfigurationImproved(ctx, clients.kubeClient.AdmissionregistrationV1(), recorder, t, cache) } case *admissionregistrationv1.MutatingWebhookConfiguration: if clients.kubeClient == nil { result.Error = fmt.Errorf("missing kubeClient") } else { - result.Result, result.Changed, result.Error = ApplyMutatingWebhookConfiguration(ctx, clients.kubeClient.AdmissionregistrationV1(), recorder, t) + result.Result, result.Changed, result.Error = ApplyMutatingWebhookConfigurationImproved(ctx, clients.kubeClient.AdmissionregistrationV1(), recorder, t, cache) } case *storagev1.CSIDriver: if clients.kubeClient == nil { diff --git a/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/helpers.go b/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/helpers.go index 46d5c13b0c..de48550f6f 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/helpers.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/helpers.go @@ -383,3 +383,42 @@ func InjectObservedProxyIntoContainers(podSpec *corev1.PodSpec, containerNames [ return nil } + +func InjectTrustedCAIntoContainers(podSpec *corev1.PodSpec, configMapName string, containerNames []string) error { + podSpec.Volumes = append(podSpec.Volumes, corev1.Volume{ + Name: "non-standard-root-system-trust-ca-bundle", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: configMapName, + }, + Items: []corev1.KeyToPath{ + {Key: "ca-bundle.crt", Path: "tls-ca-bundle.pem"}, + }, + }, + }, + }) + + for _, containerName := range containerNames { + for i := range podSpec.InitContainers { + if podSpec.InitContainers[i].Name == containerName { + podSpec.InitContainers[i].VolumeMounts = append(podSpec.InitContainers[i].VolumeMounts, corev1.VolumeMount{ + Name: "non-standard-root-system-trust-ca-bundle", + MountPath: "/etc/pki/ca-trust/extracted/pem", + ReadOnly: true, + }) + } + } + for i := range podSpec.Containers { + if podSpec.Containers[i].Name == containerName { + podSpec.Containers[i].VolumeMounts = append(podSpec.Containers[i].VolumeMounts, corev1.VolumeMount{ + Name: "non-standard-root-system-trust-ca-bundle", + MountPath: "/etc/pki/ca-trust/extracted/pem", + ReadOnly: true, + }) + } + } + } + + return nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 1e6682d07e..00666872bd 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -374,7 +374,7 @@ github.com/openshift/build-machinery-go/make/targets/golang github.com/openshift/build-machinery-go/make/targets/openshift github.com/openshift/build-machinery-go/make/targets/openshift/operator github.com/openshift/build-machinery-go/scripts -# github.com/openshift/library-go v0.0.0-20211220195323-eca2c467c492 +# github.com/openshift/library-go v0.0.0-20220121154930-b7889002d63e ## explicit; go 1.17 github.com/openshift/library-go/pkg/controller/factory github.com/openshift/library-go/pkg/controller/fileobserver