github.com/operator-framework/operator-lifecycle-manager@v0.30.0/test/e2e/packagemanifest_e2e_test.go (about) 1 package e2e 2 3 import ( 4 "context" 5 "encoding/base64" 6 "encoding/json" 7 8 "github.com/blang/semver/v4" 9 . "github.com/onsi/ginkgo/v2" 10 . "github.com/onsi/gomega" 11 opver "github.com/operator-framework/api/pkg/lib/version" 12 "github.com/operator-framework/api/pkg/operators/v1alpha1" 13 corev1 "k8s.io/api/core/v1" 14 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 15 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 16 "k8s.io/client-go/rest" 17 18 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned" 19 "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry" 20 "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient" 21 packagev1 "github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/apis/operators/v1" 22 pmversioned "github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/client/clientset/versioned" 23 "github.com/operator-framework/operator-lifecycle-manager/test/e2e/ctx" 24 ) 25 26 var _ = Describe("Package Manifest API lists available Operators from Catalog Sources", func() { 27 var ( 28 crc versioned.Interface 29 pmc pmversioned.Interface 30 c operatorclient.ClientInterface 31 generatedNamespace corev1.Namespace 32 ) 33 34 BeforeEach(func() { 35 crc = ctx.Ctx().OperatorClient() 36 pmc = newPMClient() 37 c = ctx.Ctx().KubeClient() 38 39 generatedNamespace = SetupGeneratedTestNamespace(genName("package-manifest-e2e")) 40 }) 41 42 AfterEach(func() { 43 TearDown(generatedNamespace.GetName()) 44 }) 45 46 Context("Given a CatalogSource created using the ConfigMap as catalog source type", func() { 47 var ( 48 catsrcName string 49 packageName string 50 packageAlpha string 51 alphaChannel string 52 packageStable string 53 stableChannel string 54 csvAlpha v1alpha1.ClusterServiceVersion 55 csv v1alpha1.ClusterServiceVersion 56 cleanupCatalogSource cleanupFunc 57 ) 58 59 BeforeEach(func() { 60 By(`create a simple catalogsource`) 61 packageName = genName("nginx") 62 alphaChannel = "alpha" 63 packageAlpha = packageName + "-alpha" 64 stableChannel = "stable" 65 packageStable = packageName + "-stable" 66 manifests := []registry.PackageManifest{ 67 { 68 PackageName: packageName, 69 Channels: []registry.PackageChannel{ 70 {Name: alphaChannel, CurrentCSVName: packageAlpha}, 71 {Name: stableChannel, CurrentCSVName: packageStable}, 72 }, 73 DefaultChannelName: stableChannel, 74 }, 75 } 76 77 crdPlural := genName("ins") 78 crd := newCRD(crdPlural) 79 catsrcName = genName("mock-ocs") 80 csv = newCSV(packageStable, generatedNamespace.GetName(), "", semver.MustParse("0.1.0"), []apiextensionsv1.CustomResourceDefinition{crd}, nil, nil) 81 csv.SetLabels(map[string]string{"projected": "label"}) 82 csv.Spec.Keywords = []string{"foo", "bar"} 83 csv.Spec.Links = []v1alpha1.AppLink{ 84 { 85 Name: "foo", 86 URL: "example.com", 87 }, 88 } 89 csv.Spec.Maintainers = []v1alpha1.Maintainer{ 90 { 91 Name: "foo", 92 Email: "example@gmail.com", 93 }, 94 } 95 csv.Spec.Maturity = "foo" 96 csv.Spec.NativeAPIs = []metav1.GroupVersionKind{{Group: "kubenative.io", Version: "v1", Kind: "Native"}} 97 csv.Spec.Icon = []v1alpha1.Icon{ 98 { 99 Data: "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", 100 MediaType: "image/png", 101 }, 102 } 103 104 csvAlpha = *csv.DeepCopy() 105 csvAlpha.SetName(packageAlpha) 106 csvAlpha.Spec.Version = opver.OperatorVersion{Version: semver.MustParse("0.1.1")} 107 csvAlpha.Spec.Replaces = csv.GetName() 108 csvAlpha.Spec.Icon = []v1alpha1.Icon{ 109 { 110 Data: base64.StdEncoding.EncodeToString([]byte(csvAlpha.GetName())), 111 MediaType: "image/png", 112 }, 113 } 114 115 _, cleanupCatalogSource = createInternalCatalogSource(c, crc, catsrcName, generatedNamespace.GetName(), manifests, []apiextensionsv1.CustomResourceDefinition{crd}, []v1alpha1.ClusterServiceVersion{csv, csvAlpha}) 116 117 By(`Verify catalog source was created`) 118 _, err := fetchCatalogSourceOnStatus(crc, catsrcName, generatedNamespace.GetName(), catalogSourceRegistryPodSynced()) 119 Expect(err).ToNot(HaveOccurred()) 120 }) 121 122 AfterEach(func() { 123 if cleanupCatalogSource != nil { 124 cleanupCatalogSource() 125 } 126 }) 127 128 It("retrieves the PackageManifest by package name and validates its fields", func() { 129 By(`Drop icons to account for pruning`) 130 csvAlpha.Spec.Icon = nil 131 csv.Spec.Icon = nil 132 133 csvAlphaJSON, err := json.Marshal(csvAlpha) 134 Expect(err).ToNot(HaveOccurred()) 135 csvJSON, err := json.Marshal(csv) 136 Expect(err).ToNot(HaveOccurred()) 137 138 expectedStatus := packagev1.PackageManifestStatus{ 139 CatalogSource: catsrcName, 140 CatalogSourceNamespace: generatedNamespace.GetName(), 141 PackageName: packageName, 142 Channels: []packagev1.PackageChannel{ 143 { 144 Name: alphaChannel, 145 CurrentCSV: packageAlpha, 146 CurrentCSVDesc: packagev1.CreateCSVDescription(&csvAlpha, string(csvAlphaJSON)), 147 Entries: []packagev1.ChannelEntry{ 148 { 149 Name: csvAlpha.Name, 150 Version: csvAlpha.Spec.Version.String(), 151 }, 152 { 153 Name: csv.Name, 154 Version: csv.Spec.Version.String(), 155 }, 156 }, 157 }, 158 { 159 Name: stableChannel, 160 CurrentCSV: packageStable, 161 CurrentCSVDesc: packagev1.CreateCSVDescription(&csv, string(csvJSON)), 162 Entries: []packagev1.ChannelEntry{ 163 { 164 Name: csv.Name, 165 Version: csv.Spec.Version.String(), 166 }, 167 }, 168 }, 169 }, 170 DefaultChannel: stableChannel, 171 } 172 173 pm, err := fetchPackageManifest(pmc, generatedNamespace.GetName(), packageName, packageManifestHasStatus) 174 Expect(err).ToNot(HaveOccurred(), "error getting package manifest") 175 Expect(pm).ShouldNot(BeNil()) 176 Expect(pm.GetName()).Should(Equal(packageName)) 177 Expect(pm.Status).Should(Equal(expectedStatus)) 178 Expect(pm.GetLabels()["projected"]).Should(Equal("label")) 179 Expect(pm.GetLabels()["operatorframework.io/arch.amd64"]).Should(Equal("supported")) 180 Expect(pm.GetLabels()["operatorframework.io/os.linux"]).Should(Equal("supported")) 181 }) 182 183 It("lists PackageManifest and ensures it has valid PackageManifest item", func() { 184 By(`Get a PackageManifestList and ensure it has the correct items`) 185 Eventually(func() (bool, error) { 186 pmList, err := pmc.OperatorsV1().PackageManifests(generatedNamespace.GetName()).List(context.TODO(), metav1.ListOptions{}) 187 return containsPackageManifest(pmList.Items, packageName), err 188 }).Should(BeTrue(), "required package name not found in the list") 189 }) 190 191 It("gets the icon from the default channel", func() { 192 var res rest.Result 193 Eventually(func() error { 194 res = pmc.OperatorsV1().RESTClient().Get().Resource("packagemanifests").SubResource("icon").Namespace(generatedNamespace.GetName()).Name(packageName).Do(context.Background()) 195 return res.Error() 196 }).Should(Succeed(), "error getting icon") 197 198 data, err := res.Raw() 199 Expect(err).ToNot(HaveOccurred()) 200 201 By(`Match against icon from the default`) 202 expected, err := base64.StdEncoding.DecodeString(csv.Spec.Icon[0].Data) 203 Expect(err).ToNot(HaveOccurred()) 204 Expect(data).To(Equal(expected)) 205 }) 206 }) 207 208 Context("Given a CatalogSource created using gRPC catalog source type", func() { 209 var ( 210 packageName, displayName string 211 catalogSource *v1alpha1.CatalogSource 212 ) 213 214 BeforeEach(func() { 215 sourceName := genName("catalog-") 216 packageName = "etcd-test" 217 displayName = "etcd test catalog" 218 image := "quay.io/olmtest/catsrc-update-test:related" 219 220 catalogSource = &v1alpha1.CatalogSource{ 221 TypeMeta: metav1.TypeMeta{ 222 Kind: v1alpha1.CatalogSourceKind, 223 APIVersion: v1alpha1.CatalogSourceCRDAPIVersion, 224 }, 225 ObjectMeta: metav1.ObjectMeta{ 226 Name: sourceName, 227 Namespace: generatedNamespace.GetName(), 228 Labels: map[string]string{"olm.catalogSource": sourceName}, 229 }, 230 Spec: v1alpha1.CatalogSourceSpec{ 231 SourceType: v1alpha1.SourceTypeGrpc, 232 Image: image, 233 DisplayName: displayName, 234 GrpcPodConfig: &v1alpha1.GrpcPodConfig{ 235 SecurityContextConfig: v1alpha1.Restricted, 236 }, 237 }, 238 } 239 240 var err error 241 catalogSource, err = crc.OperatorsV1alpha1().CatalogSources(catalogSource.GetNamespace()).Create(context.TODO(), catalogSource, metav1.CreateOptions{}) 242 Expect(err).NotTo(HaveOccurred()) 243 244 By(`Wait for the CatalogSource to be ready`) 245 _, err = fetchCatalogSourceOnStatus(crc, catalogSource.GetName(), catalogSource.GetNamespace(), catalogSourceRegistryPodSynced()) 246 Expect(err).ToNot(HaveOccurred(), "catalog source did not become ready") 247 }) 248 249 AfterEach(func() { 250 err := crc.OperatorsV1alpha1().CatalogSources(catalogSource.GetNamespace()).Delete(context.TODO(), catalogSource.GetName(), metav1.DeleteOptions{}) 251 Expect(err).NotTo(HaveOccurred()) 252 }) 253 254 It("lists the CatalogSource contents using the PackageManifest API", func() { 255 256 pm, err := fetchPackageManifest(pmc, generatedNamespace.GetName(), packageName, packageManifestHasStatus) 257 Expect(err).NotTo(HaveOccurred(), "error getting package manifest") 258 Expect(pm).ShouldNot(BeNil()) 259 Expect(pm.GetName()).Should(Equal(packageName)) 260 261 By(`Verify related images from the package manifest`) 262 relatedImages := pm.Status.Channels[0].CurrentCSVDesc.RelatedImages 263 264 Expect(relatedImages).To(ConsistOf([]string{ 265 "quay.io/coreos/etcd@sha256:3816b6daf9b66d6ced6f0f966314e2d4f894982c6b1493061502f8c2bf86ac84", 266 "quay.io/coreos/etcd@sha256:49d3d4a81e0d030d3f689e7167f23e120abf955f7d08dbedf3ea246485acee9f", 267 "quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2", 268 }), "Expected images to exist in the related images list\n") 269 }) 270 271 When("the display name for catalog source is updated", func() { 272 273 BeforeEach(func() { 274 pm, err := fetchPackageManifest(pmc, generatedNamespace.GetName(), packageName, packageManifestHasStatus) 275 Expect(err).NotTo(HaveOccurred(), "error getting package manifest") 276 Expect(pm).ShouldNot(BeNil()) 277 Expect(pm.GetName()).Should(Equal(packageName)) 278 Expect(pm.Status.CatalogSourceDisplayName).Should(Equal(displayName)) 279 280 catalogSource, err = crc.OperatorsV1alpha1().CatalogSources(generatedNamespace.GetName()).Get(context.TODO(), catalogSource.GetName(), metav1.GetOptions{}) 281 Expect(err).NotTo(HaveOccurred(), "error getting catalogSource") 282 283 displayName = "updated Name" 284 catalogSource.Spec.DisplayName = displayName 285 catalogSource, err = crc.OperatorsV1alpha1().CatalogSources(generatedNamespace.GetName()).Update(context.TODO(), catalogSource, metav1.UpdateOptions{}) 286 Expect(err).NotTo(HaveOccurred(), "error updating catalogSource") 287 Expect(catalogSource.Spec.DisplayName).Should(Equal(displayName)) 288 }) 289 290 It("should successfully update the CatalogSource field", func() { 291 292 Eventually(func() (string, error) { 293 pm, err := fetchPackageManifest(pmc, generatedNamespace.GetName(), packageName, 294 packageManifestHasStatus) 295 if err != nil { 296 return "", err 297 } 298 return pm.Status.CatalogSourceDisplayName, nil 299 }).Should(Equal(displayName)) 300 }) 301 }) 302 }) 303 }) 304 305 type packageManifestCheckFunc func(*packagev1.PackageManifest) bool 306 307 func packageManifestHasStatus(pm *packagev1.PackageManifest) bool { 308 // as long as it has a package name we consider the status non-empty 309 return pm != nil && pm.Status.PackageName != "" 310 } 311 312 func fetchPackageManifest(pmc pmversioned.Interface, namespace, name string, check packageManifestCheckFunc) (*packagev1.PackageManifest, error) { 313 var fetched *packagev1.PackageManifest 314 var err error 315 316 EventuallyWithOffset(1, func() (bool, error) { 317 ctx.Ctx().Logf("Polling...") 318 fetched, err = pmc.OperatorsV1().PackageManifests(namespace).Get(context.TODO(), name, metav1.GetOptions{}) 319 if err != nil { 320 return false, err 321 } 322 return check(fetched), nil 323 }).Should(BeTrue()) 324 325 return fetched, err 326 } 327 328 func containsPackageManifest(pmList []packagev1.PackageManifest, pkgName string) bool { 329 for _, pm := range pmList { 330 if pm.GetName() == pkgName { 331 return true 332 } 333 } 334 return false 335 }