github.com/operator-framework/operator-lifecycle-manager@v0.30.0/test/e2e/skopeo.go (about) 1 package e2e 2 3 import ( 4 "context" 5 "fmt" 6 "os/exec" 7 "path" 8 9 "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient" 10 "k8s.io/utils/ptr" 11 12 corev1 "k8s.io/api/core/v1" 13 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 14 ) 15 16 const ( 17 insecure = "--insecure-policy=true" 18 skopeo = "skopeo" 19 debug = "--debug" 20 skipTLS = "--dest-tls-verify=false" 21 skipCreds = "--dest-no-creds=true" 22 destCreds = "--dest-authfile=" 23 v2format = "--format=v2s2" 24 skopeoImage = "quay.io/skopeo/stable:v1.15.0" 25 BuilderServiceAccount = "builder" 26 authPath = "/mnt/registry-auth" 27 cachePath = ".local" 28 ) 29 30 func getRegistryAuthSecretName(client operatorclient.ClientInterface, namespace string) (string, error) { 31 var sa *corev1.ServiceAccount 32 var err error 33 34 // wait for the builder service account to exist and contain image pull secrets 35 err = waitFor(func() (bool, error) { 36 sa, err = client.KubernetesInterface().CoreV1().ServiceAccounts(namespace).Get(context.TODO(), BuilderServiceAccount, metav1.GetOptions{}) 37 if err != nil { 38 return false, err 39 } 40 return len(sa.ImagePullSecrets) > 0, nil 41 }) 42 43 if err != nil { 44 return "", err 45 } 46 47 secretName := sa.ImagePullSecrets[0].Name 48 secret, err := client.KubernetesInterface().CoreV1().Secrets(namespace).Get(context.TODO(), secretName, metav1.GetOptions{}) 49 if err != nil { 50 return "", err 51 } 52 return secret.GetName(), nil 53 } 54 55 func skopeoCopyCmd(newImage, newTag, oldImage, oldTag, auth string) []string { 56 newImageName := fmt.Sprint(newImage, newTag) 57 oldImageName := fmt.Sprint(oldImage, oldTag) 58 59 var creds string 60 if auth == "" { 61 creds = skipCreds 62 } else { 63 creds = fmt.Sprint(destCreds, path.Join(cachePath, "auth.json")) 64 } 65 66 cmd := []string{debug, insecure, "copy", skipTLS, v2format, creds, oldImageName, newImageName} 67 68 return cmd 69 } 70 71 func createSkopeoPod(client operatorclient.ClientInterface, args []string, namespace string, registrySecret string) error { 72 pod := &corev1.Pod{ 73 ObjectMeta: metav1.ObjectMeta{ 74 Name: skopeo, 75 Namespace: namespace, 76 Labels: map[string]string{"name": skopeo}, 77 }, 78 Spec: corev1.PodSpec{ 79 SecurityContext: &corev1.PodSecurityContext{ 80 SeccompProfile: &corev1.SeccompProfile{ 81 Type: corev1.SeccompProfileTypeRuntimeDefault, 82 }, 83 }, 84 Containers: []corev1.Container{ 85 { 86 Name: skopeo, 87 Image: skopeoImage, 88 Args: args, 89 SecurityContext: &corev1.SecurityContext{ 90 ReadOnlyRootFilesystem: ptr.To(false), 91 AllowPrivilegeEscalation: ptr.To(false), 92 Capabilities: &corev1.Capabilities{ 93 Drop: []corev1.Capability{"ALL"}, 94 }, 95 RunAsNonRoot: ptr.To(true), 96 RunAsUser: ptr.To(int64(1001)), 97 }, 98 }, 99 }, 100 RestartPolicy: corev1.RestartPolicyNever, 101 // ServiceAccountName: "builder", 102 }, 103 } 104 105 if registrySecret != "" { 106 // update container command to first convert the dockercfg to an auth.json file that skopeo can use 107 authJsonPath := path.Join(cachePath, "auth.json") 108 authJson := "\"{\\\"auths\\\": $(cat /mnt/registry-auth/.dockercfg)}\"" 109 cmd := fmt.Sprintf("echo %s > %s && exec skopeo $@", authJson, authJsonPath) 110 111 pod.Spec.Containers[0].Command = []string{"bash", "-c", cmd} 112 113 pod.Spec.Containers[0].VolumeMounts = []corev1.VolumeMount{ 114 { 115 Name: "registry-auth", 116 MountPath: authPath, 117 ReadOnly: true, 118 }, { 119 Name: "cache", 120 MountPath: cachePath, 121 ReadOnly: false, 122 }, 123 } 124 pod.Spec.Volumes = []corev1.Volume{ 125 { 126 Name: "registry-auth", 127 VolumeSource: corev1.VolumeSource{ 128 Secret: &corev1.SecretVolumeSource{ 129 SecretName: registrySecret, 130 }, 131 }, 132 }, 133 { 134 Name: "cache", 135 VolumeSource: corev1.VolumeSource{ 136 EmptyDir: &corev1.EmptyDirVolumeSource{}, 137 }, 138 }, 139 } 140 } 141 142 _, err := client.KubernetesInterface().CoreV1().Pods(namespace).Create(context.TODO(), pod, metav1.CreateOptions{}) 143 if err != nil { 144 return err 145 } 146 return nil 147 } 148 149 func deleteSkopeoPod(client operatorclient.ClientInterface, namespace string) error { 150 err := client.KubernetesInterface().CoreV1().Pods(namespace).Delete(context.TODO(), skopeo, metav1.DeleteOptions{}) 151 if err != nil { 152 return err 153 } 154 return nil 155 } 156 157 func skopeoLocalCopy(newImage, newTag string, oldImage, oldTag string) (string, error) { 158 newImageName := fmt.Sprint(newImage, newTag) 159 oldImageName := fmt.Sprint(oldImage, oldTag) 160 cmd := exec.Command(skopeo, debug, insecure, "copy", skipTLS, v2format, skipCreds, oldImageName, newImageName) 161 162 out, err := cmd.Output() 163 fmt.Println(string(out)) 164 if err != nil { 165 return "", fmt.Errorf("failed to exec %#v: %v", cmd.Args, err) 166 } 167 168 return newImageName, nil 169 }