diff --git a/cmd/authentication-operator/main.go b/cmd/authentication-operator/main.go index 529253026..b6a8b9feb 100644 --- a/cmd/authentication-operator/main.go +++ b/cmd/authentication-operator/main.go @@ -9,12 +9,11 @@ import ( "github.com/openshift/cluster-authentication-operator/pkg/cmd/render" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericiooptions" - "k8s.io/client-go/rest" "k8s.io/component-base/cli" kmshealth "github.com/openshift/library-go/pkg/operator/encryption/kms/health" + "github.com/openshift/library-go/pkg/operator/encryption/kms/health/writers" kmspreflight "github.com/openshift/library-go/pkg/operator/encryption/kms/preflight" - "github.com/openshift/library-go/pkg/operator/v1helpers" ) func main() { @@ -42,11 +41,7 @@ func NewAuthenticationOperatorCommand() *cobra.Command { cmd.AddCommand(mom.NewInputResourcesCommand(ioStreams)) cmd.AddCommand(mom.NewOutputResourcesCommand(ioStreams)) cmd.AddCommand(render.NewRender()) - cmd.AddCommand(kmshealth.NewCommand(context.Background(), func(config *rest.Config) (v1helpers.OperatorClient, error) { - // TODO: replace with a real operator client once the health reporter's condition writer - // is implemented in library-go. - return nil, nil - })) + cmd.AddCommand(kmshealth.NewCommand(context.Background(), writers.NewAuthenticationWriter)) cmd.AddCommand(kmspreflight.NewCommand(context.Background())) return cmd diff --git a/go.mod b/go.mod index 789d9d575..1320f5179 100644 --- a/go.mod +++ b/go.mod @@ -142,3 +142,7 @@ require ( ) replace github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20251001123353-fd5b1fb35db1 + +// TEMPORARY: pin library-go to the fork head of openshift/library-go#2318 (health reporter writer). +// Drop this replace and bump the require above once #2318 merges to master. +replace github.com/openshift/library-go => github.com/ibihim/library-go v0.0.0-20260626140759-4f827b89b547 diff --git a/go.sum b/go.sum index 2a86a8f77..fe5782606 100644 --- a/go.sum +++ b/go.sum @@ -136,6 +136,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5uk github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= +github.com/ibihim/library-go v0.0.0-20260626140759-4f827b89b547 h1:yUuUiyQvdUGqpYUdkeofrIR3rUIbyaS9RPqevC7w9HI= +github.com/ibihim/library-go v0.0.0-20260626140759-4f827b89b547/go.mod h1:8d0qQEDq2kpIZmaE1tKpvZ4pLeQZT+mW2JpqAh3iZIc= github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -178,8 +180,6 @@ github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af h1:Ui github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af/go.mod h1:8jcm8UPtg2mCAsxfqKil1xrmRMI3a+XU2TZ9fF8A7TE= github.com/openshift/client-go v0.0.0-20260622130833-df412d4d283e h1:NrVmCwy3vBk6UTY+cNNFHbnB40FyusJmeUIInQod/v8= github.com/openshift/client-go v0.0.0-20260622130833-df412d4d283e/go.mod h1:lMQvYPtn6LrPO/YX2j5xdv2h6BRWgYVq1tMA3qA3N9k= -github.com/openshift/library-go v0.0.0-20260625074842-d80d43df888c h1:VqRxJg5ipu/TqDA0UXBc2O8SKVnUVh20cRUoec7J1dw= -github.com/openshift/library-go v0.0.0-20260625074842-d80d43df888c/go.mod h1:8d0qQEDq2kpIZmaE1tKpvZ4pLeQZT+mW2JpqAh3iZIc= github.com/openshift/multi-operator-manager v0.0.0-20241205181422-20aa3906b99d h1:Rzx23P63JFNNz5D23ubhC0FCN5rK8CeJhKcq5QKcdyU= github.com/openshift/multi-operator-manager v0.0.0-20241205181422-20aa3906b99d/go.mod h1:iVi9Bopa5cLhjG5ie9DoZVVqkH8BGb1FQVTtecOLn4I= github.com/openshift/oauth-apiserver v0.0.0-20260520145010-97a820bd5412 h1:oDB0GmUXLp8y85fWz+LGRE0hM5JqbXTfNPi5GjEqiX0= diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/health/cmd.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/health/cmd.go index e0d413040..d1f540e3f 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/health/cmd.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/health/cmd.go @@ -6,50 +6,46 @@ import ( "regexp" "time" - "github.com/openshift/library-go/pkg/operator/v1helpers" "github.com/spf13/cobra" - "github.com/spf13/pflag" - "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/server" k8senvelopekmsv2 "k8s.io/apiserver/pkg/storage/value/encrypt/envelope/kmsv2" "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" "k8s.io/klog/v2" + + applyoperatorv1 "github.com/openshift/client-go/operator/applyconfigurations/operator/v1" ) -const Subcommand = "kms-health-reporter" +const ( + Subcommand = "kms-health-reporter" +) // kmsSocketPattern matches the socket path each co-located KMSv2 plugin is // mounted at, e.g. unix:///var/run/kmsplugin/kms-1.sock. var kmsSocketPattern = regexp.MustCompile(`^unix:///var/run/kmsplugin/kms-(\d+)\.sock$`) -// options' flag-bound fields are exported so the struct can be logged as a -// whole via klog.InfoS, which JSON-marshals its values. -type options struct { - KMSSockets []string - Interval time.Duration - ReadTimeout time.Duration - WriteTimeout time.Duration - NodeName string - Kubeconfig string - - newOperatorClient func(*rest.Config) (v1helpers.OperatorClient, error) -} +// NewEncryptionStatusWriterFunc builds the EncryptionStatusWriter for a target +// apiserver operator status CR. fieldManager sets the owner in the +// managedFields when doing SSA. +type NewEncryptionStatusWriterFunc func(restConfig *rest.Config, fieldManager string) (EncryptionStatusWriter, error) + +// EncryptionStatusWriter is capable of applying the +// KMSEncryptionStatusApplyConfiguration at the correct place in the operator's +// status. +type EncryptionStatusWriter func(ctx context.Context, status *applyoperatorv1.KMSEncryptionStatusApplyConfiguration) error type Config struct { - operatorClient v1helpers.OperatorClient - prober *prober + writeStatus EncryptionStatusWriter + prober *prober interval time.Duration writeTimeout time.Duration - nodeName string } -func NewCommand(ctx context.Context, newOperatorClient func(*rest.Config) (v1helpers.OperatorClient, error)) *cobra.Command { +func NewCommand(ctx context.Context, newWriter NewEncryptionStatusWriterFunc) *cobra.Command { o := &options{ - newOperatorClient: newOperatorClient, + newWriter: newWriter, } cmd := &cobra.Command{ @@ -78,80 +74,17 @@ func NewCommand(ctx context.Context, newOperatorClient func(*rest.Config) (v1hel return cmd } -func (o *options) addFlags(fs *pflag.FlagSet) { - fs.StringSliceVar(&o.KMSSockets, "kms-sockets", nil, "KMS plugin endpoints in unix:// URI format (e.g. unix:///var/run/kmsplugin/kms-1.sock)") - fs.DurationVar(&o.Interval, "interval", 30*time.Second, "cadence between probe+emit cycles") - fs.DurationVar(&o.ReadTimeout, "read-timeout", 5*time.Second, "deadline for each Status RPC") - fs.DurationVar(&o.WriteTimeout, "write-timeout", 10*time.Second, "deadline for each condition update") - fs.StringVar(&o.NodeName, "node-name", "", "node name recorded in the condition used to help to identify the origin") - fs.StringVar(&o.Kubeconfig, "kubeconfig", "", "path to a kubeconfig; empty uses in-cluster config") -} - -func (o *options) validate() error { - if len(o.KMSSockets) == 0 { - return fmt.Errorf("--kms-sockets is required, at least one") - } - socketSet := sets.New[string]() - for _, s := range o.KMSSockets { - if !kmsSocketPattern.MatchString(s) { - return fmt.Errorf("--kms-sockets entry %q must match %s", s, kmsSocketPattern) - } - if socketSet.Has(s) { - return fmt.Errorf("--kms-sockets entry %q is duplicated", s) - } - socketSet.Insert(s) - } - - if o.Interval <= 0 { - return fmt.Errorf("--interval must be positive") - } - if o.ReadTimeout <= 0 { - return fmt.Errorf("--read-timeout must be positive") - } - if o.WriteTimeout <= 0 { - return fmt.Errorf("--write-timeout must be positive") - } - if o.NodeName == "" { - return fmt.Errorf("--node-name is required") - } - - return nil -} - -func (o *options) Config(ctx context.Context) (*Config, error) { - // Empty kubeconfig falls back to the in-cluster config (service account - // token + KUBERNETES_SERVICE_HOST), which is the deployed path. - restCfg, err := clientcmd.BuildConfigFromFlags("", o.Kubeconfig) - if err != nil { - return nil, fmt.Errorf("build rest config: %w", err) - } - - operatorClient, err := o.newOperatorClient(restCfg) - if err != nil { - return nil, fmt.Errorf("build operator client: %w", err) - } - - plugins, err := buildPlugins(ctx, o.KMSSockets, o.ReadTimeout) - if err != nil { - return nil, err - } - - return &Config{ - operatorClient: operatorClient, - prober: newProber(plugins), - interval: o.Interval, - writeTimeout: o.WriteTimeout, - nodeName: o.NodeName, - }, nil -} - func (c *Config) Run(ctx context.Context) error { wait.JitterUntilWithContext(ctx, func(ctx context.Context) { // Each Status RPC enforces the read timeout internally (set at dial // time); ctx here only carries shutdown cancellation. - conditions := c.prober.probeAll(ctx) - // TODO: hand conditions to the writer once it lands; logging is a placeholder. - klog.InfoS("kms plugin health", "conditions", conditions) + reports := c.prober.probeAll(ctx) + + writeCtx, cancel := context.WithTimeout(ctx, c.writeTimeout) + defer cancel() + if err := c.writeStatus(writeCtx, reports); err != nil { + klog.ErrorS(err, "failed to publish kms plugin health") + } }, c.interval, 0.1, false) return nil @@ -168,7 +101,7 @@ func buildPlugins(ctx context.Context, sockets []string, timeout time.Duration) // Unique name per plugin so the gRPC client's KMS operation metrics // don't merge both plugins into one series. - service, err := k8senvelopekmsv2.NewGRPCService(ctx, socket, Subcommand+"-"+keyID, timeout) + service, err := k8senvelopekmsv2.NewGRPCService(ctx, socket, Subcommand, timeout) if err != nil { // With the current dependency version this should never happen with a validated GRPC endpoint. return nil, fmt.Errorf("setting up grpc service failed at %q: %w", socket, err) diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/health/options.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/health/options.go new file mode 100644 index 000000000..ebbd672aa --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/health/options.go @@ -0,0 +1,97 @@ +package health + +import ( + "context" + "fmt" + "time" + + "github.com/spf13/pflag" + + metav1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/client-go/tools/clientcmd" +) + +// options' flag-bound fields are exported so the struct can be logged as a +// whole via klog.InfoS, which JSON-marshals its values. +type options struct { + KMSSockets []string + Interval time.Duration + ReadTimeout time.Duration + WriteTimeout time.Duration + NodeName string + Kubeconfig string + + newWriter NewEncryptionStatusWriterFunc +} + +func (o *options) addFlags(fs *pflag.FlagSet) { + fs.StringSliceVar(&o.KMSSockets, "kms-sockets", nil, "KMS plugin endpoints in unix:// URI format (e.g. unix:///var/run/kmsplugin/kms-1.sock)") + fs.DurationVar(&o.Interval, "interval", 30*time.Second, "cadence between probe+emit cycles") + fs.DurationVar(&o.ReadTimeout, "read-timeout", 5*time.Second, "deadline for each Status RPC") + fs.DurationVar(&o.WriteTimeout, "write-timeout", 10*time.Second, "deadline for each condition update") + fs.StringVar(&o.NodeName, "node-name", "", "node name recorded in the condition used to help to identify the origin") + fs.StringVar(&o.Kubeconfig, "kubeconfig", "", "path to a kubeconfig; empty uses in-cluster config") +} + +func (o *options) validate() error { + if len(o.KMSSockets) == 0 { + return fmt.Errorf("--kms-sockets is required, at least one") + } + socketSet := sets.New[string]() + for _, s := range o.KMSSockets { + if !kmsSocketPattern.MatchString(s) { + return fmt.Errorf("--kms-sockets entry %q must match %s", s, kmsSocketPattern) + } + if socketSet.Has(s) { + return fmt.Errorf("--kms-sockets entry %q is duplicated", s) + } + socketSet.Insert(s) + } + + if o.Interval <= 0 { + return fmt.Errorf("--interval must be positive") + } + if o.ReadTimeout <= 0 { + return fmt.Errorf("--read-timeout must be positive") + } + if o.WriteTimeout <= 0 { + return fmt.Errorf("--write-timeout must be positive") + } + if o.NodeName == "" { + return fmt.Errorf("--node-name is required") + } + if fieldManager := fmt.Sprintf("%s-%s", Subcommand, o.NodeName); len(fieldManager) > metav1validation.FieldManagerMaxLength { + return fmt.Errorf("--node-name too long: reporter identity %q is %d chars, exceeds the %d-char fieldManager limit", fieldManager, len(fieldManager), metav1validation.FieldManagerMaxLength) + } + + return nil +} + +func (o *options) Config(ctx context.Context) (*Config, error) { + // Empty kubeconfig falls back to the in-cluster config (service account + // token + KUBERNETES_SERVICE_HOST), which is the deployed path. + restCfg, err := clientcmd.BuildConfigFromFlags("", o.Kubeconfig) + if err != nil { + return nil, fmt.Errorf("build rest config: %w", err) + } + + // fieldManager is the per-node ownership-identity. + fieldManager := fmt.Sprintf("%s-%s", Subcommand, o.NodeName) + writeStatus, err := o.newWriter(restCfg, fieldManager) + if err != nil { + return nil, fmt.Errorf("build encryption status writer: %w", err) + } + + plugins, err := buildPlugins(ctx, o.KMSSockets, o.ReadTimeout) + if err != nil { + return nil, err + } + + return &Config{ + writeStatus: writeStatus, + prober: newProber(o.NodeName, plugins), + interval: o.Interval, + writeTimeout: o.WriteTimeout, + }, nil +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/health/prober.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/health/prober.go index 84db02fe1..55f05edb4 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/health/prober.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/health/prober.go @@ -2,31 +2,22 @@ package health import ( "context" + "errors" "sync" "time" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kmsservice "k8s.io/kms/pkg/service" + + operatorv1 "github.com/openshift/api/operator/v1" + applyoperatorv1 "github.com/openshift/client-go/operator/applyconfigurations/operator/v1" ) // healthzOK is the value the KMS plugin returns when healthy. // See https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/kms/apis/v2/api.proto#L39 const healthzOK = "ok" -const ( - statusHealthy = "healthy" - statusUnhealthy = "unhealthy" - statusError = "error" -) - -type pluginHealthReport struct { - // KeyID is the controller's sequential key id; KEKID is the KMS provider's - // encryption key id. Distinct identifiers, easy to confuse. - KeyID string - KEKID string - Status string - LastChecked time.Time - Detail string -} +var errResponseless error = errors.New("kms plugin returned nil status response") // pluginClient is the dialed handle to one co-located KMS plugin; the plugin // itself is a separate process behind the unix socket. @@ -36,14 +27,16 @@ type pluginClient struct { } type prober struct { - plugins []pluginClient - now func() time.Time + nodeName string + plugins []pluginClient + now func() time.Time } -func newProber(plugins []pluginClient) *prober { +func newProber(nodeName string, plugins []pluginClient) *prober { return &prober{ - plugins: plugins, - now: time.Now, + nodeName: nodeName, + plugins: plugins, + now: time.Now, } } @@ -51,8 +44,8 @@ func newProber(plugins []pluginClient) *prober { // with Status "error" so the caller always gets one entry per plugin. // Probes run concurrently so one hung plugin doesn't delay the others; // worst-case duration is one read-timeout, not the sum. -func (p *prober) probeAll(ctx context.Context) []pluginHealthReport { - reports := make([]pluginHealthReport, len(p.plugins)) +func (p *prober) probeAll(ctx context.Context) *applyoperatorv1.KMSEncryptionStatusApplyConfiguration { + reports := make([]*applyoperatorv1.KMSPluginHealthReportApplyConfiguration, len(p.plugins)) var wg sync.WaitGroup for i, plugin := range p.plugins { @@ -62,31 +55,31 @@ func (p *prober) probeAll(ctx context.Context) []pluginHealthReport { } wg.Wait() - return reports + return applyoperatorv1.KMSEncryptionStatus().WithHealthReports(reports...) } -func (p *prober) probe(ctx context.Context, plugin pluginClient) pluginHealthReport { - report := pluginHealthReport{ - KeyID: plugin.keyID, - LastChecked: p.now(), - } +func (p *prober) probe(ctx context.Context, plugin pluginClient) *applyoperatorv1.KMSPluginHealthReportApplyConfiguration { + report := applyoperatorv1.KMSPluginHealthReport(). + WithNodeName(p.nodeName). + WithKeyId(plugin.keyID). + WithLastCheckedTime(metav1.NewTime(p.now())) resp, err := plugin.service.Status(ctx) switch { case err != nil: - report.Status = statusError - report.Detail = err.Error() + report.WithStatus(operatorv1.KMSPluginHealthStatusError). + WithDetail(err.Error()) case resp == nil: // The in-tree gRPC client never returns (nil, nil), but a misbehaving // plugin must not panic the reporter. - report.Status = statusError - report.Detail = "kms plugin returned nil status response" + report.WithStatus(operatorv1.KMSPluginHealthStatusError). + WithDetail(errResponseless.Error()) case resp.Healthz == healthzOK: - report.Status = statusHealthy - report.KEKID = resp.KeyID + report.WithStatus(operatorv1.KMSPluginHealthStatusHealthy). + WithKEKId(resp.KeyID) default: - report.Status = statusUnhealthy - report.Detail = resp.Healthz + report.WithStatus(operatorv1.KMSPluginHealthStatusUnhealthy). + WithDetail(resp.Healthz) } return report diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/health/writers/writers.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/health/writers/writers.go new file mode 100644 index 000000000..5a866e68c --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/kms/health/writers/writers.go @@ -0,0 +1,85 @@ +// Package writers provides the per-operator EncryptionStatusWriter +// implementations for the KMS health reporter. +// +// The health package builds the shared leaf (KMSEncryptionStatus) and ships the +// reporter command; each apiserver operator nests that leaf into a different +// status CR. These constructors carry that per-operator placement so an operator +// wires one function into health.NewCommand instead of hand-rolling the apply. +package writers + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/rest" + + applyoperatorv1 "github.com/openshift/client-go/operator/applyconfigurations/operator/v1" + operatorclient "github.com/openshift/client-go/operator/clientset/versioned" + + "github.com/openshift/library-go/pkg/operator/encryption/kms/health" +) + +// NewAuthenticationWriter writes into Authentication/cluster at +// .status.oauthAPIServer.encryptionStatus. The auth operator manages the +// oauth-apiserver. There is an extra hop the other two operators don't have. +func NewAuthenticationWriter(restConfig *rest.Config, fieldManager string) (health.EncryptionStatusWriter, error) { + client, err := operatorclient.NewForConfig(restConfig) + if err != nil { + return nil, err + } + + return func(ctx context.Context, status *applyoperatorv1.KMSEncryptionStatusApplyConfiguration) error { + _, err := client.OperatorV1().Authentications().ApplyStatus( + ctx, + applyoperatorv1.Authentication("cluster").WithStatus( + applyoperatorv1.AuthenticationStatus().WithOAuthAPIServer( + applyoperatorv1.OAuthAPIServerStatus().WithEncryptionStatus(status), + ), + ), + + metav1.ApplyOptions{FieldManager: fieldManager, Force: true}, + ) + return err + }, nil +} + +// NewKubeAPIServerWriter writes into KubeAPIServer/cluster at +// .status.encryptionStatus. +func NewKubeAPIServerWriter(restConfig *rest.Config, fieldManager string) (health.EncryptionStatusWriter, error) { + client, err := operatorclient.NewForConfig(restConfig) + if err != nil { + return nil, err + } + + return func(ctx context.Context, status *applyoperatorv1.KMSEncryptionStatusApplyConfiguration) error { + _, err := client.OperatorV1().KubeAPIServers().ApplyStatus( + ctx, + applyoperatorv1.KubeAPIServer("cluster").WithStatus( + applyoperatorv1.KubeAPIServerStatus().WithEncryptionStatus(status), + ), + metav1.ApplyOptions{FieldManager: fieldManager, Force: true}, + ) + return err + }, nil +} + +// NewOpenShiftAPIServerWriter writes into OpenShiftAPIServer/cluster at +// .status.encryptionStatus. +func NewOpenShiftAPIServerWriter(restConfig *rest.Config, fieldManager string) (health.EncryptionStatusWriter, error) { + client, err := operatorclient.NewForConfig(restConfig) + if err != nil { + return nil, err + } + + return func(ctx context.Context, status *applyoperatorv1.KMSEncryptionStatusApplyConfiguration) error { + _, err := client.OperatorV1().OpenShiftAPIServers().ApplyStatus( + ctx, + applyoperatorv1.OpenShiftAPIServer("cluster").WithStatus( + applyoperatorv1.OpenShiftAPIServerStatus().WithEncryptionStatus(status), + ), + + metav1.ApplyOptions{FieldManager: fieldManager, Force: true}, + ) + return err + }, nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 0bab55928..53341561a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -411,7 +411,7 @@ github.com/openshift/client-go/user/applyconfigurations/internal github.com/openshift/client-go/user/applyconfigurations/user/v1 github.com/openshift/client-go/user/clientset/versioned/scheme github.com/openshift/client-go/user/clientset/versioned/typed/user/v1 -# github.com/openshift/library-go v0.0.0-20260625074842-d80d43df888c +# github.com/openshift/library-go v0.0.0-20260625074842-d80d43df888c => github.com/ibihim/library-go v0.0.0-20260626140759-4f827b89b547 ## explicit; go 1.25.0 github.com/openshift/library-go/pkg/apiserver/jsonpatch github.com/openshift/library-go/pkg/apps/deployment @@ -457,6 +457,7 @@ github.com/openshift/library-go/pkg/operator/encryption/deployer github.com/openshift/library-go/pkg/operator/encryption/encoding github.com/openshift/library-go/pkg/operator/encryption/encryptiondata github.com/openshift/library-go/pkg/operator/encryption/kms/health +github.com/openshift/library-go/pkg/operator/encryption/kms/health/writers github.com/openshift/library-go/pkg/operator/encryption/kms/pluginlifecycle github.com/openshift/library-go/pkg/operator/encryption/kms/preflight github.com/openshift/library-go/pkg/operator/encryption/observer @@ -1687,3 +1688,4 @@ sigs.k8s.io/structured-merge-diff/v6/value ## explicit; go 1.22 sigs.k8s.io/yaml # github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20251001123353-fd5b1fb35db1 +# github.com/openshift/library-go => github.com/ibihim/library-go v0.0.0-20260626140759-4f827b89b547