Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@
"environmentSelector": {}
},
{
"name": "[sig-olmv1][OCPFeatureGate:NewOLM][Skipped:Disconnected] OLMv1 operator installation should install a cluster extension",
"name": "[sig-olmv1][OCPFeatureGate:NewOLM][Skipped:Disconnected] OLMv1 operator installation should install an openshift catalog cluster extension",
"labels": {},
"resources": {
"isolation": {}
Expand All @@ -485,8 +485,24 @@
"environmentSelector": {}
},
{
"name": "[sig-olmv1][OCPFeatureGate:NewOLM][Skipped:Disconnected] OLMv1 operator installation should fail to install a non-existing cluster extension",
"labels": {},
"name": "[sig-olmv1][OCPFeatureGate:NewOLM] OLMv1 operator installation should install a cluster extension",
"originalName": "[sig-olmv1][OCPFeatureGate:NewOLM][Skipped:Disconnected] OLMv1 operator installation should install a cluster extension",
"labels": {
"original-name:[sig-olmv1][OCPFeatureGate:NewOLM][Skipped:Disconnected] OLMv1 operator installation should install a cluster extension": {}
},
"resources": {
"isolation": {}
},
"source": "openshift:payload:olmv1",
"lifecycle": "blocking",
"environmentSelector": {}
},
{
"name": "[sig-olmv1][OCPFeatureGate:NewOLM] OLMv1 operator installation should fail to install a non-existing cluster extension",
"originalName": "[sig-olmv1][OCPFeatureGate:NewOLM][Skipped:Disconnected] OLMv1 operator installation should fail to install a non-existing cluster extension",
"labels": {
"original-name:[sig-olmv1][OCPFeatureGate:NewOLM][Skipped:Disconnected] OLMv1 operator installation should fail to install a non-existing cluster extension": {}
},
"resources": {
"isolation": {}
},
Expand Down
10 changes: 5 additions & 5 deletions openshift/tests-extension/pkg/bindata/operator/operator.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

199 changes: 168 additions & 31 deletions openshift/tests-extension/test/olmv1.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
//nolint:staticcheck // ST1001: dot-imports for readability
. "github.com/onsi/gomega"

"github.com/openshift/origin/test/extended/util/image"
corev1 "k8s.io/api/core/v1"
apiextclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/apimachinery/pkg/api/meta"
Expand All @@ -19,6 +20,8 @@ import (

olmv1 "github.com/operator-framework/operator-controller/api/v1"

catalogdata "github.com/openshift/operator-framework-operator-controller/openshift/tests-extension/pkg/bindata/catalog"
operatordata "github.com/openshift/operator-framework-operator-controller/openshift/tests-extension/pkg/bindata/operator"
"github.com/openshift/operator-framework-operator-controller/openshift/tests-extension/pkg/env"
"github.com/openshift/operator-framework-operator-controller/openshift/tests-extension/pkg/helpers"
)
Expand Down Expand Up @@ -71,6 +74,8 @@ var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLM] OLMv1 CRDs", func() {
})
})

// Keeping this test as skip:disconnected, so we can attempt to install a "real" operator, rather than a generated one
// There is an equivalent in-cluster positive test below
var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLM][Skipped:Disconnected] OLMv1 operator installation", func() {
var (
namespace string
Expand Down Expand Up @@ -102,7 +107,7 @@ var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLM][Skipped:Disconnected] OLMv1
}
})

It("should install a cluster extension", func(ctx SpecContext) {
It("should install an openshift catalog cluster extension", func(ctx SpecContext) {
if !env.Get().IsOpenShift {
Skip("Requires OCP Catalogs: not OpenShift")
}
Expand All @@ -117,38 +122,170 @@ var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLM][Skipped:Disconnected] OLMv1
By("waiting for the quay-operator ClusterExtension to be installed")
helpers.ExpectClusterExtensionToBeInstalled(ctx, name)
})
})

It("should fail to install a non-existing cluster extension", func(ctx SpecContext) {
By("ensuring no ClusterExtension and CRD for non-existing operator")
helpers.EnsureCleanupClusterExtension(context.Background(), "does-not-exist", "") // No CRD expected for non-existing operator
var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLM] OLMv1 operator installation", func() {
var unique, nsName, ccName, rbName, opName string
BeforeEach(func(ctx SpecContext) {
helpers.RequireOLMv1CapabilityOnOpenshift()
unique = rand.String(8)
nsName = "install-test-ns-" + unique
ccName = "install-test-cc-" + unique
rbName = "install-test-rb-" + unique
opName = "install-test-op-" + unique

By("applying the ClusterExtension resource")
name, cleanup := helpers.CreateClusterExtension("does-not-exist", "99.99.99", namespace, "")
DeferCleanup(cleanup)
By(fmt.Sprintf("setting a unique value: %q", unique))

testVersion := env.Get().OpenShiftVersion
replacements := map[string]string{
"{{ TEST-BUNDLE }}": opName,
"{{ NAMESPACE }}": nsName,
"{{ VERSION }}": testVersion,

// Using the shell image provided by origin as the controller image.
// The image is mirrored into disconnected environments for testing.
"{{ TEST-CONTROLLER }}": image.ShellImage(),
}

By("creating a new Namespace")
nsCleanup := createNamespace(nsName)
DeferCleanup(nsCleanup)

// The builder (and deployer) service accounts are created by OpenShift itself which injects them in the NS.
By(fmt.Sprintf("waiting for builder serviceaccount in %s", nsName))
helpers.ExpectServiceAccountExists(ctx, "builder", nsName)

By(fmt.Sprintf("waiting for deployer serviceaccount in %s", nsName))
helpers.ExpectServiceAccountExists(ctx, "deployer", nsName)

By("applying image-puller RoleBinding")
rbCleanup := createImagePullerRoleBinding(rbName, nsName)
DeferCleanup(rbCleanup)

By("creating the operator BuildConfig")
bcCleanup := createBuildConfig(opName, nsName)
DeferCleanup(bcCleanup)

By("creating the operator ImageStream")
isCleanup := createImageStream(opName, nsName)
DeferCleanup(isCleanup)

By("creating the operator tarball")
fileOperator, fileCleanup := createTempTarBall(replacements, operatordata.AssetNames, operatordata.Asset)
DeferCleanup(fileCleanup)
By(fmt.Sprintf("created operator tarball %q", fileOperator))

By("starting the operator build via RAW URL")
opArgs := []string{
"create",
"--raw",
fmt.Sprintf(
"/apis/build.openshift.io/v1/namespaces/%s/buildconfigs/%s/instantiatebinary?name=%s&namespace=%s",
nsName, opName, opName, nsName,
),
"-f",
fileOperator,
}
buildOperator := startBuild(opArgs...)

By(fmt.Sprintf("waiting for the build %q to finish", buildOperator.Name))
waitForBuildToFinish(ctx, buildOperator.Name, nsName)

By("creating the catalog BuildConfig")
bcCleanup = createBuildConfig(ccName, nsName)
DeferCleanup(bcCleanup)

By("creating the catalog ImageStream")
isCleanup = createImageStream(ccName, nsName)
DeferCleanup(isCleanup)

By("creating the catalog tarball")
fileCatalog, fileCleanup := createTempTarBall(replacements, catalogdata.AssetNames, catalogdata.Asset)
DeferCleanup(fileCleanup)
By(fmt.Sprintf("created catalog tarball %q", fileCatalog))

By("starting the catalog build via RAW URL")
catalogArgs := []string{
"create",
"--raw",
fmt.Sprintf(
"/apis/build.openshift.io/v1/namespaces/%s/buildconfigs/%s/instantiatebinary?name=%s&namespace=%s",
nsName, ccName, ccName, nsName,
),
"-f",
fileCatalog,
}
buildCatalog := startBuild(catalogArgs...)

By(fmt.Sprintf("waiting for the build %q to finish", buildCatalog.Name))
waitForBuildToFinish(ctx, buildCatalog.Name, nsName)

By("waiting for the ClusterExtension to exist")
ce := &olmv1.ClusterExtension{}
Eventually(func() error {
return env.Get().K8sClient.Get(ctx, client.ObjectKey{Name: name}, ce)
}).WithTimeout(5 * time.Minute).WithPolling(1 * time.Second).Should(Succeed())

By("waiting up to 2 minutes for ClusterExtension to report failure")
Eventually(func(g Gomega) {
k8sClient := env.Get().K8sClient
err := k8sClient.Get(ctx, client.ObjectKey{Name: name}, ce)
g.Expect(err).ToNot(HaveOccurred())

progressing := meta.FindStatusCondition(ce.Status.Conditions, olmv1.TypeProgressing)
g.Expect(progressing).ToNot(BeNil())
g.Expect(progressing.Status).To(Equal(metav1.ConditionTrue))
g.Expect(progressing.Reason).To(Equal("Retrying"))
g.Expect(progressing.Message).To(ContainSubstring(`no bundles found`))

installed := meta.FindStatusCondition(ce.Status.Conditions, olmv1.TypeInstalled)
g.Expect(installed).ToNot(BeNil())
g.Expect(installed.Status).To(Equal(metav1.ConditionFalse))
g.Expect(installed.Reason).To(Equal("Failed"))
g.Expect(installed.Message).To(Equal("No bundle installed"))
}).WithTimeout(5 * time.Minute).WithPolling(1 * time.Second).Should(Succeed())
By("creating the ClusterCatalog")
ccCleanup := createClusterCatalog(ccName, nsName)
DeferCleanup(ccCleanup)
})

AfterEach(func(ctx SpecContext) {
if CurrentSpecReport().Failed() {
By("dumping for debugging")
helpers.DescribeAllClusterCatalogs(context.Background())
helpers.DescribeAllClusterExtensions(context.Background(), nsName)
}
})

It("should install a cluster extension",
Label("original-name:[sig-olmv1][OCPFeatureGate:NewOLM][Skipped:Disconnected] OLMv1 operator installation should install a cluster extension"), func(ctx SpecContext) {
if !env.Get().IsOpenShift {
Skip("Requires OCP Catalogs: not OpenShift")
}

By("ensuring no ClusterExtension and CRD for the operator")
helpers.EnsureCleanupClusterExtension(context.Background(), opName, "")

By("applying the ClusterExtension resource")
name, cleanup := helpers.CreateClusterExtension(opName, "", nsName, unique, helpers.WithCatalogNameSelector(ccName))
DeferCleanup(cleanup)

By("waiting for the ClusterExtension to be installed")
helpers.ExpectClusterExtensionToBeInstalled(ctx, name)
})

It("should fail to install a non-existing cluster extension",
Label("original-name:[sig-olmv1][OCPFeatureGate:NewOLM][Skipped:Disconnected] OLMv1 operator installation should fail to install a non-existing cluster extension"), func(ctx SpecContext) {
if !env.Get().IsOpenShift {
Skip("Requires OCP APIs: not OpenShift")
}

By("ensuring no ClusterExtension and CRD for non-existing operator")
helpers.EnsureCleanupClusterExtension(context.Background(), "does-not-exist", "") // No CRD expected for non-existing operator

By("applying the ClusterExtension resource")
name, cleanup := helpers.CreateClusterExtension("does-not-exist", "99.99.99", nsName, unique, helpers.WithCatalogNameSelector(ccName))
DeferCleanup(cleanup)

By("waiting for the ClusterExtension to exist")
ce := &olmv1.ClusterExtension{}
Eventually(func() error {
return env.Get().K8sClient.Get(ctx, client.ObjectKey{Name: name}, ce)
}).WithTimeout(5 * time.Minute).WithPolling(5 * time.Second).Should(Succeed())

By("waiting up to 2 minutes for ClusterExtension to report failure")
Eventually(func(g Gomega) {
k8sClient := env.Get().K8sClient
err := k8sClient.Get(ctx, client.ObjectKey{Name: name}, ce)
g.Expect(err).ToNot(HaveOccurred())

progressing := meta.FindStatusCondition(ce.Status.Conditions, olmv1.TypeProgressing)
g.Expect(progressing).ToNot(BeNil())
g.Expect(progressing.Status).To(Equal(metav1.ConditionTrue))
g.Expect(progressing.Reason).To(Equal("Retrying"))
g.Expect(progressing.Message).To(ContainSubstring(`no bundles found`))

installed := meta.FindStatusCondition(ce.Status.Conditions, olmv1.TypeInstalled)
g.Expect(installed).ToNot(BeNil())
g.Expect(installed.Status).To(Equal(metav1.ConditionFalse))
g.Expect(installed.Reason).To(Equal("Failed"))
g.Expect(installed.Message).To(Equal("No bundle installed"))
}).WithTimeout(5 * time.Minute).WithPolling(5 * time.Second).Should(Succeed())
})
})