github.com/verrazzano/verrazzano@v1.7.1/tests/e2e/registry/registry_test.go (about) 1 // Copyright (c) 2021, 2023, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 package registry 5 6 import ( 7 "fmt" 8 "github.com/verrazzano/verrazzano/pkg/log/vzlog" 9 "github.com/verrazzano/verrazzano/pkg/nginxutil" 10 "os" 11 "strings" 12 "time" 13 14 . "github.com/onsi/ginkgo/v2" 15 . "github.com/onsi/gomega" 16 "github.com/verrazzano/verrazzano/platform-operator/constants" 17 "github.com/verrazzano/verrazzano/tests/e2e/pkg" 18 "github.com/verrazzano/verrazzano/tests/e2e/pkg/test/framework" 19 corev1 "k8s.io/api/core/v1" 20 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 ) 22 23 const ( 24 waitTimeout = 2 * time.Minute 25 pollingInterval = 10 * time.Second 26 27 extOSPod = "opensearch-cluster-master-0" 28 helmOperationPodNamePrefix = "helm-operation" 29 shellImage = "shell:" 30 ) 31 32 var registry = os.Getenv("REGISTRY") 33 34 // Map that contains the images present in the BOM with the associated registry URL 35 var imageRegistryMap = make(map[string]string) 36 37 var ingressNGINXNamespace string 38 39 var t = framework.NewTestFramework("registry") 40 var beforeSuite = t.BeforeSuiteFunc(func() { 41 var err error 42 ingressNGINXNamespace, err = nginxutil.DetermineNamespaceForIngressNGINX(vzlog.DefaultLogger()) 43 if err != nil { 44 Fail(err.Error()) 45 } 46 }) 47 var _ = BeforeSuite(beforeSuite) 48 var afterSuite = t.AfterSuiteFunc(func() {}) 49 var _ = AfterSuite(afterSuite) 50 var _ = t.AfterEach(func() {}) 51 52 var _ = t.Describe("Image Registry Verification", Label("f:platform-lcm.private-registry"), 53 func() { 54 t.It("All the pods in the cluster have the expected registry URLs", 55 func() { 56 // List of namespaces from which all the pods are queried to confirm the images are loaded from the target registry/repo 57 var listOfNamespaces = []string{ 58 "cattle-global-data", 59 "cattle-global-data-nt", 60 "cattle-system", 61 "cert-manager", 62 "default", 63 "fleet-default", 64 "fleet-local", 65 "fleet-system", 66 ingressNGINXNamespace, 67 "istio-system", 68 "keycloak", 69 "local", 70 "monitoring", 71 "verrazzano-install", 72 "verrazzano-mc", 73 "argocd", 74 constants.VerrazzanoSystemNamespace, 75 constants.VerrazzanoMonitoringNamespace, 76 } 77 foundHelmOperationPod := false 78 shellImageHasCorrectPrefix := false 79 var pod corev1.Pod 80 for i, ns := range listOfNamespaces { 81 var pods *corev1.PodList 82 Eventually(func() (*corev1.PodList, error) { 83 var err error 84 pods, err = pkg.ListPods(ns, metav1.ListOptions{}) 85 return pods, err 86 }, waitTimeout, pollingInterval).ShouldNot(BeNil(), fmt.Sprintf("Error listing pods in the namespace %s", ns)) 87 88 for j := range pods.Items { 89 pod = pods.Items[j] 90 // Skip private registry validation in case of external OpenSearch 91 if pod.Name == extOSPod { 92 continue 93 } 94 if strings.HasPrefix(pod.Name, helmOperationPodNamePrefix) { 95 foundHelmOperationPod = true 96 } 97 podLabels := pod.GetLabels() 98 _, ok := podLabels["job-name"] 99 if pod.Status.Phase != corev1.PodRunning && ok { 100 continue 101 } 102 pkg.Log(pkg.Info, fmt.Sprintf("%d. Validating the registry url prefix for pod: %s in namespace: %s", i, pod.Name, ns)) 103 for k := range pod.Spec.Containers { 104 image := pod.Spec.Containers[k].Image 105 registryURL, err := getRegistryURL(image) 106 Expect(err).To(BeNil(), fmt.Sprintf("Failed to get the expected registry url for image %s: %v", image, err)) 107 hasCorrectRegistryPrefix := strings.HasPrefix(image, registryURL) 108 109 // When checking the Rancher Helm Operation pod Shell image, there may be old pods left over so we only check to see 110 // if at least one of the Shell images has the correct registry prefix 111 if strings.Contains(image, shellImage) { 112 if hasCorrectRegistryPrefix { 113 shellImageHasCorrectPrefix = true 114 } 115 continue 116 } 117 Expect(hasCorrectRegistryPrefix).To(BeTrue(), 118 fmt.Sprintf("FAIL: The image for the pod %s in containers, doesn't start with expected registry URL prefix %s, image name %s", pod.Name, registryURL, image)) 119 } 120 for k := range pod.Spec.InitContainers { 121 image := pod.Spec.InitContainers[k].Image 122 registryURL, err := getRegistryURL(image) 123 Expect(err).To(BeNil(), fmt.Sprintf("Failed to get the expected registry url for init container image %s: %v", image, err)) 124 Expect(strings.HasPrefix(image, registryURL)).To(BeTrue(), 125 fmt.Sprintf("FAIL: The image for the pod %s in initContainers, doesn't start with expected registry URL prefix %s, image name %s", pod.Name, registryURL, image)) 126 } 127 } 128 } 129 130 // If we found at least one Rancher Helm Operation pod, then make sure at least one of the Shell images has the correct prefix 131 if foundHelmOperationPod { 132 Expect(shellImageHasCorrectPrefix).To(BeTrue(), "FAIL: Found at least one Rancher Helm Operation pod but none of the shell images has the expected registry prefix") 133 } 134 }) 135 }) 136 137 // getRegistryURL returns the private registry url if the private registry env is set 138 // If private registry is not set, the registry url is determined based on what is specified in the BOM 139 // for a given image 140 func getRegistryURL(containerImage string) (string, error) { 141 // For private registry, determine the registry url from the corresponding env variables 142 if len(registry) > 0 { 143 return pkg.GetImagePrefix(), nil 144 } 145 // Populate image registry map if not already done 146 if len(imageRegistryMap) == 0 { 147 err := populateImageRegistryMap() 148 if err != nil { 149 return "", err 150 } 151 } 152 imageName := getImageName(containerImage) 153 // Due to the Rancher images changing from vz/rancher/shell to vz/rancher-shell, this logic handles looking up both 154 // the old and new shell image names in the BOM. If neither are found, then this function returns an error. 155 if imageRegistryMap[imageName] == "" && imageName == "shell" { 156 imageName = "rancher-shell" 157 } 158 // If the image is not defined in the bom, return an error 159 if imageRegistryMap[imageName] == "" { 160 return "", fmt.Errorf("the image %s is not specified in the BOM from platform operator", imageName) 161 } 162 registryURLFromBom := imageRegistryMap[imageName] 163 // If the registry of the image is docker.io and the container image does not have the registry prefix, 164 // remove docker.io from the constructed registry url. This is mainly to address the case where some of the 165 // images such as rancher-webhook does not have "docker.io" prefix in the image in the pod output. 166 if strings.HasPrefix(registryURLFromBom, "docker.io") && !strings.HasPrefix(containerImage, "docker.io") { 167 return strings.TrimPrefix(registryURLFromBom, "docker.io/"), nil 168 } 169 return registryURLFromBom, nil 170 } 171 172 // Populate image registry map from BOM 173 func populateImageRegistryMap() error { 174 // Get the BOM from installed Platform Operator 175 bomDoc, err := pkg.GetBOMDoc() 176 if err != nil { 177 return err 178 } 179 globalRegistry := bomDoc.Registry 180 for _, component := range bomDoc.Components { 181 for _, subComponent := range component.SubComponents { 182 registry := globalRegistry 183 if len(subComponent.Registry) > 0 { 184 registry = subComponent.Registry 185 } 186 repository := subComponent.Repository 187 for _, image := range subComponent.Images { 188 if len(image.Registry) > 0 { 189 registry = image.Registry 190 } 191 if len(image.Repository) > 0 { 192 repository = image.Repository 193 } 194 imageRegistryMap[image.ImageName] = registry + "/" + repository 195 } 196 } 197 } 198 return nil 199 } 200 201 // Get the name of the image from the image URL 202 func getImageName(imageURL string) string { 203 imageWithoutVer := strings.Split(imageURL, ":")[0] 204 imageParts := strings.Split(imageWithoutVer, "/") 205 return imageParts[len(imageParts)-1] 206 }