diff --git a/pkg/cvo/updatepayload.go b/pkg/cvo/updatepayload.go index 90fa9ce3f9..46bfb0bb84 100644 --- a/pkg/cvo/updatepayload.go +++ b/pkg/cvo/updatepayload.go @@ -141,15 +141,6 @@ func (r *payloadRetriever) targetUpdatePayloadDir(ctx context.Context, update co if err := r.pruneJobs(ctx, 0); err != nil { klog.Warningf("failed to prune jobs: %v", err) } - if files, err := os.ReadDir(r.workingDir); err != nil { - klog.Warningf("failed to list update payload directory: %v", err) - } else { - for _, file := range files { - if err := os.RemoveAll(filepath.Join(r.workingDir, file.Name())); err != nil { - klog.Warningf("failed to prune update payload directory: %v", err) - } - } - } if err := payload.ValidateDirectory(tdir); os.IsNotExist(err) { // the dirs don't exist, try fetching the payload to tdir. @@ -170,16 +161,36 @@ func (r *payloadRetriever) targetUpdatePayloadDir(ctx context.Context, update co func (r *payloadRetriever) fetchUpdatePayloadToDir(ctx context.Context, dir string, update configv1.Update) error { var ( version = update.Version - payload = update.Image + image = update.Image name = fmt.Sprintf("%s-%s-%s", r.operatorName, version, randutil.String(5)) namespace = r.namespace deadline = pointer.Int64Ptr(2 * 60) nodeSelectorKey = "node-role.kubernetes.io/master" nodename = r.nodeName - cmd = []string{"/bin/sh"} - args = []string{"-c", copyPayloadCmd(dir)} ) + baseDir, targetName := filepath.Split(dir) + tmpDir := filepath.Join(baseDir, fmt.Sprintf("%s-%s", targetName, randutil.String(5))) + + setContainerDefaults := func(container corev1.Container) corev1.Container { + container.Image = image + container.VolumeMounts = []corev1.VolumeMount{{ + MountPath: targetUpdatePayloadsDir, + Name: "payloads", + }} + container.SecurityContext = &corev1.SecurityContext{ + Privileged: pointer.BoolPtr(true), + } + container.Resources = corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("10m"), + corev1.ResourceMemory: resource.MustParse("50Mi"), + corev1.ResourceEphemeralStorage: resource.MustParse("2Mi"), + }, + } + return container + } + job := &batchv1.Job{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -189,26 +200,38 @@ func (r *payloadRetriever) fetchUpdatePayloadToDir(ctx context.Context, dir stri ActiveDeadlineSeconds: deadline, Template: corev1.PodTemplateSpec{ Spec: corev1.PodSpec{ - Containers: []corev1.Container{{ - Name: "payload", - Image: payload, - Command: cmd, - Args: args, - VolumeMounts: []corev1.VolumeMount{{ - MountPath: targetUpdatePayloadsDir, - Name: "payloads", - }}, - SecurityContext: &corev1.SecurityContext{ - Privileged: pointer.BoolPtr(true), - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("10m"), - corev1.ResourceMemory: resource.MustParse("50Mi"), - corev1.ResourceEphemeralStorage: resource.MustParse("2Mi"), + InitContainers: []corev1.Container{ + setContainerDefaults(corev1.Container{ + Name: "cleanup", + Command: []string{"rm", "-fR", filepath.Join(baseDir, "*")}, + }), + setContainerDefaults(corev1.Container{ + Name: "make-temporary-directory", + Command: []string{"mkdir", tmpDir}, + }), + setContainerDefaults(corev1.Container{ + Name: "move-operator-manifests-to-temporary-directory", + Command: []string{ + "mv", + filepath.Join(payload.DefaultPayloadDir, payload.CVOManifestDir), + filepath.Join(tmpDir, payload.CVOManifestDir), }, - }, - }}, + }), + setContainerDefaults(corev1.Container{ + Name: "move-release-manifests-to-temporary-directory", + Command: []string{ + "mv", + filepath.Join(payload.DefaultPayloadDir, payload.ReleaseManifestDir), + filepath.Join(tmpDir, payload.ReleaseManifestDir), + }, + }), + }, + Containers: []corev1.Container{ + setContainerDefaults(corev1.Container{ + Name: "rename-to-final-location", + Command: []string{"mv", tmpDir, dir}, + }), + }, Volumes: []corev1.Volume{{ Name: "payloads", VolumeSource: corev1.VolumeSource{ @@ -288,24 +311,6 @@ func (r *payloadRetriever) pruneJobs(ctx context.Context, retain int) error { return nil } -// copyPayloadCmd returns a shell command that copies CVO and release manifests from the default location -// to the target dir. -// It is made up of 2 commands: -// `mkdir -p && mv ` -// `mkdir -p && mv ` -func copyPayloadCmd(tdir string) string { - var ( - fromCVOPath = filepath.Join(payload.DefaultPayloadDir, payload.CVOManifestDir) - toCVOPath = filepath.Join(tdir, payload.CVOManifestDir) - cvoCmd = fmt.Sprintf("mkdir -p %s && mv %s %s", tdir, fromCVOPath, toCVOPath) - - fromReleasePath = filepath.Join(payload.DefaultPayloadDir, payload.ReleaseManifestDir) - toReleasePath = filepath.Join(tdir, payload.ReleaseManifestDir) - releaseCmd = fmt.Sprintf("mkdir -p %s && mv %s %s", tdir, fromReleasePath, toReleasePath) - ) - return fmt.Sprintf("%s && %s", cvoCmd, releaseCmd) -} - // findUpdateFromConfig identifies a desired update from user input or returns false. It will // resolve payload if the user specifies a version and a matching available update. func findUpdateFromConfig(config *configv1.ClusterVersion) (configv1.Update, bool) {