diff --git a/go.mod b/go.mod index e2ad28c482..c12f826ffa 100644 --- a/go.mod +++ b/go.mod @@ -133,3 +133,5 @@ require ( ) replace github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 + +replace github.com/openshift/library-go => github.com/tchap/library-go v0.0.0-20250930140150-ccd7851e777c diff --git a/go.sum b/go.sum index c7c603b0bb..e7698cc86d 100644 --- a/go.sum +++ b/go.sum @@ -165,8 +165,6 @@ github.com/openshift/build-machinery-go v0.0.0-20250530140348-dc5b2804eeee h1:+S github.com/openshift/build-machinery-go v0.0.0-20250530140348-dc5b2804eeee/go.mod h1:8jcm8UPtg2mCAsxfqKil1xrmRMI3a+XU2TZ9fF8A7TE= github.com/openshift/client-go v0.0.0-20250710075018-396b36f983ee h1:tOtrrxfDEW8hK3eEsHqxsXurq/D6LcINGfprkQC3hqY= github.com/openshift/client-go v0.0.0-20250710075018-396b36f983ee/go.mod h1:zhRiYyNMk89llof2qEuGPWPD+joQPhCRUc2IK0SB510= -github.com/openshift/library-go v0.0.0-20250729191057-91376e1b394e h1:xYT+P++PSc9G+Y47pIcU9fm8IDV/tg6tMi3i+0m23pU= -github.com/openshift/library-go v0.0.0-20250729191057-91376e1b394e/go.mod h1:tptKNust9MdRI0p90DoBSPHIrBa9oh+Rok59tF0vT8c= github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 h1:AKx/w1qpS8We43bsRgf8Nll3CGlDHpr/WAXvuedTNZI= github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= @@ -214,6 +212,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tchap/library-go v0.0.0-20250930140150-ccd7851e777c h1:/LpbBlOnCue1EKdHiHE+42F4+IZyKytQiso3AsVhku4= +github.com/tchap/library-go v0.0.0-20250930140150-ccd7851e777c/go.mod h1:tptKNust9MdRI0p90DoBSPHIrBa9oh+Rok59tF0vT8c= github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= diff --git a/vendor/github.com/openshift/library-go/pkg/operator/certrotation/client_cert_rotation_controller.go b/vendor/github.com/openshift/library-go/pkg/operator/certrotation/client_cert_rotation_controller.go index 0d6ffe6738..06441f37e8 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/certrotation/client_cert_rotation_controller.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/certrotation/client_cert_rotation_controller.go @@ -6,6 +6,7 @@ import ( "time" operatorv1 "github.com/openshift/api/operator/v1" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/wait" "github.com/openshift/library-go/pkg/controller/factory" @@ -82,7 +83,22 @@ func NewCertRotationController( return factory.New(). ResyncEvery(time.Minute). WithSync(c.Sync). - WithInformers( + WithFilteredEventsInformers( + func(obj interface{}) bool { + if cm, ok := obj.(*corev1.ConfigMap); ok { + return cm.Namespace == caBundleConfigMap.Namespace && cm.Name == caBundleConfigMap.Name + } + if secret, ok := obj.(*corev1.Secret); ok { + if secret.Namespace == rotatedSigningCASecret.Namespace && secret.Name == rotatedSigningCASecret.Name { + return true + } + if secret.Namespace == rotatedSelfSignedCertKeySecret.Namespace && secret.Name == rotatedSelfSignedCertKeySecret.Name { + return true + } + return false + } + return true + }, rotatedSigningCASecret.Informer.Informer(), caBundleConfigMap.Informer.Informer(), rotatedSelfSignedCertKeySecret.Informer.Informer(), diff --git a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/storage.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/storage.go index 3199d2db05..d44a5d571a 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/storage.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/storage.go @@ -142,6 +142,9 @@ func ApplyCSIDriver(ctx context.Context, client storageclientv1.CSIDriversGetter if required.Annotations == nil { required.Annotations = map[string]string{} } + if required.Labels == nil { + required.Labels = map[string]string{} + } if err := SetSpecHashAnnotation(&required.ObjectMeta, required.Spec); err != nil { return nil, false, err } diff --git a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceread/networking.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceread/networking.go index 9832ede719..2953e3bd11 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceread/networking.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceread/networking.go @@ -18,7 +18,7 @@ func init() { } func ReadNetworkPolicyV1OrDie(objBytes []byte) *networkingv1.NetworkPolicy { - requiredObj, err := runtime.Decode(coreCodecs.UniversalDecoder(networkingv1.SchemeGroupVersion), objBytes) + requiredObj, err := runtime.Decode(netCodecs.UniversalDecoder(networkingv1.SchemeGroupVersion), objBytes) if err != nil { panic(err) } diff --git a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/certsyncpod/certsync_controller.go b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/certsyncpod/certsync_controller.go index 111776d994..31e44b7ff7 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/certsyncpod/certsync_controller.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/certsyncpod/certsync_controller.go @@ -17,8 +17,8 @@ import ( "github.com/openshift/library-go/pkg/controller/factory" "github.com/openshift/library-go/pkg/operator/events" - "github.com/openshift/library-go/pkg/operator/staticpod" "github.com/openshift/library-go/pkg/operator/staticpod/controller/installer" + "github.com/openshift/library-go/pkg/operator/staticpod/internal/atomicfiles" ) type CertSyncController struct { @@ -115,7 +115,7 @@ func (c *CertSyncController) sync(ctx context.Context, syncCtx factory.SyncConte contentDir := getConfigMapDir(c.destinationDir, cm.Name) - data := map[string]string{} + data := make(map[string]string, len(configMap.Data)) for filename := range configMap.Data { fullFilename := filepath.Join(contentDir, filename) @@ -152,27 +152,7 @@ func (c *CertSyncController) sync(ctx context.Context, syncCtx factory.SyncConte continue } - klog.Infof("Creating directory %q ...", contentDir) - if err := os.MkdirAll(contentDir, 0755); err != nil && !os.IsExist(err) { - c.eventRecorder.Warningf("CertificateUpdateFailed", "Failed creating directory for configmap: %s/%s: %v", configMap.Namespace, configMap.Name, err) - errors = append(errors, err) - continue - } - for filename, content := range configMap.Data { - fullFilename := filepath.Join(contentDir, filename) - // if the existing is the same, do nothing - if reflect.DeepEqual(data[fullFilename], content) { - continue - } - - klog.Infof("Writing configmap manifest %q ...", fullFilename) - if err := staticpod.WriteFileAtomic([]byte(content), 0644, fullFilename); err != nil { - c.eventRecorder.Warningf("CertificateUpdateFailed", "Failed writing file for configmap: %s/%s: %v", configMap.Namespace, configMap.Name, err) - errors = append(errors, err) - continue - } - } - c.eventRecorder.Eventf("CertificateUpdated", "Wrote updated configmap: %s/%s", configMap.Namespace, configMap.Name) + errors = append(errors, syncDirectory(c.eventRecorder, "configmap", configMap.ObjectMeta, contentDir, data, 0644)) } klog.Infof("Syncing secrets: %v", c.secrets) @@ -220,7 +200,7 @@ func (c *CertSyncController) sync(ctx context.Context, syncCtx factory.SyncConte contentDir := getSecretDir(c.destinationDir, s.Name) - data := map[string][]byte{} + data := make(map[string][]byte, len(secret.Data)) for filename := range secret.Data { fullFilename := filepath.Join(contentDir, filename) @@ -257,29 +237,20 @@ func (c *CertSyncController) sync(ctx context.Context, syncCtx factory.SyncConte continue } - klog.Infof("Creating directory %q ...", contentDir) - if err := os.MkdirAll(contentDir, 0755); err != nil && !os.IsExist(err) { - c.eventRecorder.Warningf("CertificateUpdateFailed", "Failed creating directory for secret: %s/%s: %v", secret.Namespace, secret.Name, err) - errors = append(errors, err) - continue - } - for filename, content := range secret.Data { - // TODO fix permissions - fullFilename := filepath.Join(contentDir, filename) - // if the existing is the same, do nothing - if reflect.DeepEqual(data[fullFilename], content) { - continue - } - - klog.Infof("Writing secret manifest %q ...", fullFilename) - if err := staticpod.WriteFileAtomic(content, 0600, fullFilename); err != nil { - c.eventRecorder.Warningf("CertificateUpdateFailed", "Failed writing file for secret: %s/%s: %v", secret.Namespace, secret.Name, err) - errors = append(errors, err) - continue - } - } - c.eventRecorder.Eventf("CertificateUpdated", "Wrote updated secret: %s/%s", secret.Namespace, secret.Name) + errors = append(errors, syncDirectory(c.eventRecorder, "secret", secret.ObjectMeta, contentDir, data, 0600)) } - return utilerrors.NewAggregate(errors) } + +func syncDirectory[C string | []byte]( + eventRecorder events.Recorder, + typeName string, o metav1.ObjectMeta, + targetDir string, files map[string]C, filePerm os.FileMode, +) error { + if err := atomicfiles.SyncDirectory(typeName, o, targetDir, files, filePerm); err != nil { + eventRecorder.Warning("CertificateUpdateFailed", err.Error()) + return err + } + eventRecorder.Eventf("CertificateUpdated", "Wrote updated %s: %s/%s", typeName, o.Namespace, o.Name) + return nil +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/certsyncpod/hash_directory.go b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/certsyncpod/hash_directory.go new file mode 100644 index 0000000000..90c5aa77a4 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/certsyncpod/hash_directory.go @@ -0,0 +1,30 @@ +package certsyncpod + +import ( + "bytes" + "crypto/md5" + "encoding/binary" + "io/fs" + "path/filepath" +) + +func hashDirectory(root string) ([]byte, error) { + var b bytes.Buffer + if err := filepath.Walk(root, func(path string, info fs.FileInfo, err error) error { + if err != nil { + return err + } + // We do not hash the root directory entry itself. + if path == root { + return nil + } + + b.WriteString(path) + binary.Write(&b, binary.LittleEndian, info.ModTime().UnixNano()) + return nil + }); err != nil { + return nil, err + } + + return md5.New().Sum(b.Bytes()), nil +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/installerpod/cmd.go b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/installerpod/cmd.go index 5d065b40fc..658fac1936 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/installerpod/cmd.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/installerpod/cmd.go @@ -3,7 +3,6 @@ package installerpod import ( "context" "fmt" - "k8s.io/utils/clock" "os" "path" "sort" @@ -11,28 +10,28 @@ import ( "strings" "time" - "k8s.io/apimachinery/pkg/util/wait" - "github.com/blang/semver/v4" "github.com/davecgh/go-spew/spew" "github.com/spf13/cobra" "github.com/spf13/pflag" - "k8s.io/klog/v2" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/uuid" + "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/server" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" + "k8s.io/klog/v2" + "k8s.io/utils/clock" "github.com/openshift/library-go/pkg/config/client" "github.com/openshift/library-go/pkg/operator/events" "github.com/openshift/library-go/pkg/operator/resource/resourceread" "github.com/openshift/library-go/pkg/operator/resource/retry" - "github.com/openshift/library-go/pkg/operator/staticpod" "github.com/openshift/library-go/pkg/operator/staticpod/internal" + "github.com/openshift/library-go/pkg/operator/staticpod/internal/atomicfiles" "github.com/openshift/library-go/pkg/operator/staticpod/internal/flock" ) @@ -258,15 +257,9 @@ func (o *InstallOptions) copySecretsAndConfigMaps(ctx context.Context, resourceD secretBaseName = o.prefixFor(secret.Name) } contentDir := path.Join(resourceDir, "secrets", secretBaseName) - klog.Infof("Creating directory %q ...", contentDir) - if err := os.MkdirAll(contentDir, 0755); err != nil { + if err := atomicfiles.SyncDirectory("secret", secret.ObjectMeta, contentDir, secret.Data, 0600); err != nil { return err } - for filename, content := range secret.Data { - if err := writeSecret(content, path.Join(contentDir, filename)); err != nil { - return err - } - } } for _, configmap := range configs { configMapBaseName := configmap.Name @@ -274,17 +267,10 @@ func (o *InstallOptions) copySecretsAndConfigMaps(ctx context.Context, resourceD configMapBaseName = o.prefixFor(configmap.Name) } contentDir := path.Join(resourceDir, "configmaps", configMapBaseName) - klog.Infof("Creating directory %q ...", contentDir) - if err := os.MkdirAll(contentDir, 0755); err != nil { + if err := atomicfiles.SyncDirectory("configmap", configmap.ObjectMeta, contentDir, configmap.Data, 0600); err != nil { return err } - for filename, content := range configmap.Data { - if err := writeConfig([]byte(content), path.Join(contentDir, filename)); err != nil { - return err - } - } } - return nil } @@ -624,23 +610,3 @@ func (o *InstallOptions) writePod(rawPodBytes []byte, manifestFileName, resource } return nil } - -func writeConfig(content []byte, fullFilename string) error { - klog.Infof("Writing config file %q ...", fullFilename) - - filePerms := os.FileMode(0600) - if strings.HasSuffix(fullFilename, ".sh") { - filePerms = 0755 - } - return staticpod.WriteFileAtomic(content, filePerms, fullFilename) -} - -func writeSecret(content []byte, fullFilename string) error { - klog.Infof("Writing secret manifest %q ...", fullFilename) - - filePerms := os.FileMode(0600) - if strings.HasSuffix(fullFilename, ".sh") { - filePerms = 0700 - } - return staticpod.WriteFileAtomic(content, filePerms, fullFilename) -} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/internal/atomicfiles/swap_directories_linux.go b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/internal/atomicfiles/swap_directories_linux.go new file mode 100644 index 0000000000..0fdaa4bd45 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/internal/atomicfiles/swap_directories_linux.go @@ -0,0 +1,33 @@ +//go:build linux + +package atomicfiles + +import ( + "fmt" + "path/filepath" + + "golang.org/x/sys/unix" +) + +// SwapDirectories can be used to swap two directories atomically. +// +// This function requires absolute paths and will return an error if that's not the case. +func SwapDirectories(dirA, dirB string) error { + if !filepath.IsAbs(dirA) { + return fmt.Errorf("not an absolute path: %q", dirA) + } + if !filepath.IsAbs(dirB) { + return fmt.Errorf("not an absolute path: %q", dirB) + } + + // Renameat2 can be used to exchange two directories atomically when RENAME_EXCHANGE flag is specified. + // The paths to be exchanged can be specified in multiple ways: + // + // * You can specify a file descriptor and a relative path to that descriptor. + // * You can specify an absolute path, in which case the file descriptor is ignored. + // + // We make sure the path is absolute, hence we pass 0 as the file descriptor as it is ignored. + // + // For more details, see `man renameat2` as that is the associated C library function. + return unix.Renameat2(0, dirA, 0, dirB, unix.RENAME_EXCHANGE) +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/internal/atomicfiles/swap_directories_other.go b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/internal/atomicfiles/swap_directories_other.go new file mode 100644 index 0000000000..2168491a94 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/internal/atomicfiles/swap_directories_other.go @@ -0,0 +1,41 @@ +//go:build !linux + +package atomicfiles + +import ( + "fmt" + "math/rand/v2" + "os" + "path/filepath" +) + +// SwapDirectories swaps two directories, but NOT atomically in this case. +// Atomic implementation is only available for Linux. +// This function is essentially a mock for tests, and it simply uses os.Rename. +// In case there is any error, the swapping process is left in an inconsistent state. +func SwapDirectories(dirA, dirB string) error { + // Still retain the constraints as in the Linux implementation. + if !filepath.IsAbs(dirA) { + return fmt.Errorf("not an absolute path: %q", dirA) + } + if !filepath.IsAbs(dirB) { + return fmt.Errorf("not an absolute path: %q", dirB) + } + + // Rename dirA -> prevDirA. + prevDirA := fmt.Sprintf("%s-%d", dirA, rand.Int64()) + if err := os.Rename(dirA, prevDirA); err != nil { + return fmt.Errorf("failed to rename %q to %q: %w", dirA, prevDirA, err) + } + + // Rename dirB -> dirA. + if err := os.Rename(dirB, dirA); err != nil { + return fmt.Errorf("failed to rename %q to %q: %w", dirB, dirA, err) + } + + // Rename prevDirA -> dirB. + if err := os.Rename(prevDirA, dirB); err != nil { + return fmt.Errorf("failed to rename %q to %q: %w", prevDirA, dirB, err) + } + return nil +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/internal/atomicfiles/sync_directory.go b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/internal/atomicfiles/sync_directory.go new file mode 100644 index 0000000000..74bdfcf32f --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/internal/atomicfiles/sync_directory.go @@ -0,0 +1,89 @@ +package atomicfiles + +import ( + "fmt" + "os" + "path/filepath" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/klog/v2" +) + +// SyncDirectory can be used to atomically synchronize target directory with the given file content map. +// This is done by populating a temporary directory, then atomically swapping it with the target directory. +// This effectively means that any extra files in the target directory are pruned. +// +// SyncDirectory is supposed to be used with secrets/configmaps, so typeName is expected to be "configmap" or "secret". +// This does not affect the logic, but it's included in error messages. +func SyncDirectory[C string | []byte]( + typeName string, o metav1.ObjectMeta, targetDir string, files map[string]C, filePerm os.FileMode, +) error { + return syncDirectory(&realFS, typeName, o, targetDir, files, filePerm) +} + +type fileSystem struct { + MkdirAll func(path string, perm os.FileMode) error + MkdirTemp func(dir, pattern string) (string, error) + RemoveAll func(path string) error + WriteFile func(name string, data []byte, perm os.FileMode) error + SwapDirectoriesAtomic func(dirA, dirB string) error +} + +var realFS = fileSystem{ + MkdirAll: os.MkdirAll, + MkdirTemp: os.MkdirTemp, + RemoveAll: os.RemoveAll, + WriteFile: os.WriteFile, + SwapDirectoriesAtomic: SwapDirectories, +} + +func syncDirectory[C string | []byte]( + fs *fileSystem, typeName string, o metav1.ObjectMeta, + targetDir string, files map[string]C, filePerm os.FileMode, +) error { + // We are doing to prepare a tmp directory and write all files into that directory. + // Then we are going to atomically swap the new data directory for the old one. + // This is currently implemented as really atomically exchanging directories. + // + // The same goal of atomic swap could be implemented using symlinks much like AtomicWriter does in + // https://github.com/kubernetes/kubernetes/blob/v1.34.0/pkg/volume/util/atomic_writer.go#L58 + // The reason we don't do that is that we already have a directory populated and watched that needs to we swapped, + // in other words, it's for compatibility reasons. And if we were to migrate to the symlink approach, + // we would anyway need to atomically turn the current data directory to a symlink. + // This would all just increase complexity and require atomic swap on the OS level anyway. + + // In case the target directory does not exist, create it so that the directory not existing is not a special case. + klog.Infof("Ensuring content directory %q exists ...", targetDir) + if err := fs.MkdirAll(targetDir, 0755); err != nil && !os.IsExist(err) { + return fmt.Errorf("failed creating content directory for %s: %s/%s: %w", typeName, o.Namespace, o.Name, err) + } + + // Create a tmp source directory to be swapped. + klog.Infof("Creating temporary directory to swap for %q ...", targetDir) + tmpDir, err := fs.MkdirTemp(filepath.Dir(targetDir), filepath.Base(targetDir)+"-*") + if err != nil { + return fmt.Errorf("failed creating temporary directory for %s: %s/%s: %w", typeName, o.Namespace, o.Name, err) + } + defer func() { + if err := fs.RemoveAll(tmpDir); err != nil { + klog.Errorf("Failed to remove temporary directory %q during cleanup: %v", tmpDir, err) + } + }() + + // Populate the tmp directory with files. + for filename, content := range files { + fullFilename := filepath.Join(tmpDir, filename) + klog.Infof("Writing %s manifest %q ...", typeName, fullFilename) + + if err := fs.WriteFile(fullFilename, []byte(content), filePerm); err != nil { + return fmt.Errorf("failed writing file for %s: %s/%s: %w", typeName, o.Namespace, o.Name, err) + } + } + + // Swap directories atomically. + klog.Infof("Atomically swapping target directory %q with temporary directory %q for %s: %s/%s ...", targetDir, tmpDir, typeName, o.Namespace, o.Name) + if err := fs.SwapDirectoriesAtomic(targetDir, tmpDir); err != nil { + return fmt.Errorf("failed swapping target directory %q with temporary directory %q for %s: %s/%s: %w", targetDir, tmpDir, typeName, o.Namespace, o.Name, err) + } + return nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index decc79eae2..b8cf002500 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -400,7 +400,7 @@ github.com/openshift/client-go/security/informers/externalversions/internalinter github.com/openshift/client-go/security/informers/externalversions/security github.com/openshift/client-go/security/informers/externalversions/security/v1 github.com/openshift/client-go/security/listers/security/v1 -# github.com/openshift/library-go v0.0.0-20250729191057-91376e1b394e +# github.com/openshift/library-go v0.0.0-20250729191057-91376e1b394e => github.com/tchap/library-go v0.0.0-20250930140150-ccd7851e777c ## explicit; go 1.24.0 github.com/openshift/library-go/pkg/apiserver/jsonpatch github.com/openshift/library-go/pkg/assets @@ -475,6 +475,7 @@ github.com/openshift/library-go/pkg/operator/staticpod/controller/staticpodfallb github.com/openshift/library-go/pkg/operator/staticpod/controller/staticpodstate github.com/openshift/library-go/pkg/operator/staticpod/installerpod github.com/openshift/library-go/pkg/operator/staticpod/internal +github.com/openshift/library-go/pkg/operator/staticpod/internal/atomicfiles github.com/openshift/library-go/pkg/operator/staticpod/internal/flock github.com/openshift/library-go/pkg/operator/staticpod/prune github.com/openshift/library-go/pkg/operator/staticpod/startupmonitor @@ -1659,3 +1660,4 @@ sigs.k8s.io/structured-merge-diff/v4/value sigs.k8s.io/yaml sigs.k8s.io/yaml/goyaml.v2 # github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 +# github.com/openshift/library-go => github.com/tchap/library-go v0.0.0-20250930140150-ccd7851e777c