Skip to content

Commit

Permalink
fix TestClusterExtensionInstallReResolvesWhenNewCataloge2e test
Browse files Browse the repository at this point in the history
  • Loading branch information
yashoza19 committed Jul 9, 2024
1 parent feaeece commit c0e9639
Show file tree
Hide file tree
Showing 12 changed files with 143 additions and 109 deletions.
17 changes: 10 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,10 @@ E2E_REGISTRY_NAME := docker-registry
E2E_REGISTRY_NAMESPACE := operator-controller-e2e

export REG_PKG_NAME := registry-operator
export REGISTRY_ROOT := $(E2E_REGISTRY_NAME).$(E2E_REGISTRY_NAMESPACE).svc:5000
export CATALOG_IMG := $(REGISTRY_ROOT)/e2e/test-catalog:e2e
export LOCAL_REGISTRY_HOST := $(E2E_REGISTRY_NAME).$(E2E_REGISTRY_NAMESPACE).svc:5000
export CLUSTER_REGISTRY_HOST := localhost:30000
export E2E_TEST_CATALOG_V1 := e2e/test-catalog:v1
export E2E_TEST_CATALOG_V2 := e2e/test-catalog:v2
.PHONY: test-ext-dev-e2e
test-ext-dev-e2e: $(OPERATOR_SDK) $(KUSTOMIZE) $(KIND) #HELP Run extension create, upgrade and delete tests.
test/extension-developer-e2e/setup.sh $(OPERATOR_SDK) $(CONTAINER_RUNTIME) $(KUSTOMIZE) $(KIND) $(KIND_CLUSTER_NAME) $(E2E_REGISTRY_NAMESPACE)
Expand All @@ -141,7 +143,8 @@ image-registry: ## Setup in-cluster image registry
./test/tools/image-registry.sh $(E2E_REGISTRY_NAMESPACE) $(E2E_REGISTRY_NAME)

build-push-e2e-catalog: ## Build the testdata catalog used for e2e tests and push it to the image registry
./test/tools/build-push-e2e-catalog.sh $(E2E_REGISTRY_NAMESPACE) $(CATALOG_IMG)
./test/tools/build-push-e2e-catalog.sh $(E2E_REGISTRY_NAMESPACE) $(LOCAL_REGISTRY_HOST)/$(E2E_TEST_CATALOG_V1)
./test/tools/build-push-e2e-catalog.sh $(E2E_REGISTRY_NAMESPACE) $(LOCAL_REGISTRY_HOST)/$(E2E_TEST_CATALOG_V2)

# When running the e2e suite, you can set the ARTIFACT_PATH variable to the absolute path
# of the directory for the operator-controller e2e tests to store the artifacts, which
Expand Down Expand Up @@ -189,10 +192,10 @@ kind-clean: $(KIND) #EXHELP Delete the kind cluster.
$(KIND) delete cluster --name $(KIND_CLUSTER_NAME)

registry-load-bundles: ## Load selected e2e testdata container images created in kind-load-bundles into registry
testdata/bundles/registry-v1/build-push-e2e-bundle.sh ${E2E_REGISTRY_NAMESPACE} $(REGISTRY_ROOT)/bundles/registry-v1/prometheus-operator:v1.0.0 prometheus-operator.v1.0.0 prometheus-operator.v1.0.0
testdata/bundles/registry-v1/build-push-e2e-bundle.sh ${E2E_REGISTRY_NAMESPACE} $(REGISTRY_ROOT)/bundles/registry-v1/prometheus-operator:v1.0.1 prometheus-operator.v1.0.1 prometheus-operator.v1.0.0
testdata/bundles/registry-v1/build-push-e2e-bundle.sh ${E2E_REGISTRY_NAMESPACE} $(REGISTRY_ROOT)/bundles/registry-v1/prometheus-operator:v1.2.0 prometheus-operator.v1.2.0 prometheus-operator.v1.0.0
testdata/bundles/registry-v1/build-push-e2e-bundle.sh ${E2E_REGISTRY_NAMESPACE} $(REGISTRY_ROOT)/bundles/registry-v1/prometheus-operator:v2.0.0 prometheus-operator.v2.0.0 prometheus-operator.v1.0.0
testdata/bundles/registry-v1/build-push-e2e-bundle.sh ${E2E_REGISTRY_NAMESPACE} $(LOCAL_REGISTRY_HOST)/bundles/registry-v1/prometheus-operator:v1.0.0 prometheus-operator.v1.0.0 prometheus-operator.v1.0.0
testdata/bundles/registry-v1/build-push-e2e-bundle.sh ${E2E_REGISTRY_NAMESPACE} $(LOCAL_REGISTRY_HOST)/bundles/registry-v1/prometheus-operator:v1.0.1 prometheus-operator.v1.0.1 prometheus-operator.v1.0.0
testdata/bundles/registry-v1/build-push-e2e-bundle.sh ${E2E_REGISTRY_NAMESPACE} $(LOCAL_REGISTRY_HOST)/bundles/registry-v1/prometheus-operator:v1.2.0 prometheus-operator.v1.2.0 prometheus-operator.v1.0.0
testdata/bundles/registry-v1/build-push-e2e-bundle.sh ${E2E_REGISTRY_NAMESPACE} $(LOCAL_REGISTRY_HOST)/bundles/registry-v1/prometheus-operator:v2.0.0 prometheus-operator.v2.0.0 prometheus-operator.v1.0.0

#SECTION Build

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/blang/semver/v4 v4.0.0
github.com/go-logr/logr v1.4.2
github.com/google/go-cmp v0.6.0
github.com/google/go-containerregistry v0.19.2
github.com/operator-framework/api v0.26.0
github.com/operator-framework/catalogd v0.17.0
github.com/operator-framework/helm-operator-plugins v0.2.2-0.20240520180534-f463c36fedf9
Expand Down Expand Up @@ -128,7 +129,6 @@ require (
github.com/google/btree v1.1.2 // indirect
github.com/google/cel-go v0.17.8 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-containerregistry v0.19.2 // indirect
github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20240505154900-ff385a972813 // indirect
github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20240505154900-ff385a972813 // indirect
github.com/google/gofuzz v1.2.0 // indirect
Expand Down
150 changes: 80 additions & 70 deletions test/e2e/cluster_extension_install_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package e2e
import (
"context"
"fmt"
"github.com/google/go-containerregistry/pkg/crane"

Check failure on line 6 in test/e2e/cluster_extension_install_test.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gci`-ed with --skip-generated -s standard -s dot -s default -s prefix(github.com/operator-framework) -s prefix(github.com/operator-framework/operator-controller) --custom-order (gci)
"io"
"os"
"path/filepath"
Expand Down Expand Up @@ -94,7 +95,7 @@ func TestClusterExtensionInstallRegistry(t *testing.T) {
assert.Equal(ct, metav1.ConditionTrue, cond.Status)
assert.Equal(ct, ocv1alpha1.ReasonSuccess, cond.Reason)
assert.Contains(ct, cond.Message, "resolved to")
assert.Equal(ct, &ocv1alpha1.BundleMetadata{Name: "prometheus-operator.2.0.0", Version: "2.0.0"}, clusterExtension.Status.ResolvedBundle)
assert.Equal(ct, &ocv1alpha1.BundleMetadata{Name: "prometheus-operator.1.2.0", Version: "1.2.0"}, clusterExtension.Status.ResolvedBundle)
}, pollDuration, pollInterval)

t.Log("By eventually reporting a successful unpacked")
Expand Down Expand Up @@ -123,75 +124,6 @@ func TestClusterExtensionInstallRegistry(t *testing.T) {
}, pollDuration, pollInterval)
}

func TestClusterExtensionInstallReResolvesWhenNewCatalog(t *testing.T) {
t.Log("When a cluster extension is installed from a catalog")
t.Log("It resolves again when a new catalog is available")

clusterExtension, extensionCatalog := testInit(t)
defer testCleanup(t, extensionCatalog, clusterExtension)
defer getArtifactsOutput(t)

pkgName := "prometheus"
clusterExtension.Spec = ocv1alpha1.ClusterExtensionSpec{
PackageName: pkgName,
InstallNamespace: "default",
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: "default",
},
}

t.Log("By deleting the catalog first")
require.NoError(t, c.Delete(context.Background(), extensionCatalog))
require.EventuallyWithT(t, func(ct *assert.CollectT) {
err := c.Get(context.Background(), types.NamespacedName{Name: extensionCatalog.Name}, &catalogd.ClusterCatalog{})
assert.True(ct, errors.IsNotFound(err))
}, pollDuration, pollInterval)

t.Log("By creating the ClusterExtension resource")
require.NoError(t, c.Create(context.Background(), clusterExtension))

// TODO: this isn't a good precondition because a missing package results in
// exponential backoff retries. So we can't be sure that the re-reconcile is a result of
// the catalog becoming available because it could also be a retry of the initial failed
// resolution.
t.Log("By failing to find ClusterExtension during resolution")
require.EventuallyWithT(t, func(ct *assert.CollectT) {
assert.NoError(ct, c.Get(context.Background(), types.NamespacedName{Name: clusterExtension.Name}, clusterExtension))
cond := apimeta.FindStatusCondition(clusterExtension.Status.Conditions, ocv1alpha1.TypeResolved)
if !assert.NotNil(ct, cond) {
return
}
assert.Equal(ct, metav1.ConditionFalse, cond.Status)
assert.Equal(ct, ocv1alpha1.ReasonResolutionFailed, cond.Reason)
assert.Contains(ct, cond.Message, fmt.Sprintf("no package %q found", pkgName))
}, pollDuration, pollInterval)

t.Log("By creating an ClusterExtension catalog with the desired package")
var err error
extensionCatalog, err = createTestCatalog(context.Background(), testCatalogName, os.Getenv(testCatalogRefEnvVar))
require.NoError(t, err)
require.EventuallyWithT(t, func(ct *assert.CollectT) {
assert.NoError(ct, c.Get(context.Background(), types.NamespacedName{Name: extensionCatalog.Name}, extensionCatalog))
cond := apimeta.FindStatusCondition(extensionCatalog.Status.Conditions, catalogd.TypeUnpacked)
if !assert.NotNil(ct, cond) {
return
}
assert.Equal(ct, metav1.ConditionTrue, cond.Status)
assert.Equal(ct, catalogd.ReasonUnpackSuccessful, cond.Reason)
}, pollDuration, pollInterval)

t.Log("By eventually resolving the package successfully")
require.EventuallyWithT(t, func(ct *assert.CollectT) {
assert.NoError(ct, c.Get(context.Background(), types.NamespacedName{Name: clusterExtension.Name}, clusterExtension))
cond := apimeta.FindStatusCondition(clusterExtension.Status.Conditions, ocv1alpha1.TypeResolved)
if !assert.NotNil(ct, cond) {
return
}
assert.Equal(ct, metav1.ConditionTrue, cond.Status)
assert.Equal(ct, ocv1alpha1.ReasonSuccess, cond.Reason)
}, pollDuration, pollInterval)
}

func TestClusterExtensionBlockInstallNonSuccessorVersion(t *testing.T) {
t.Log("When a cluster extension is installed from a catalog")
t.Log("When resolving upgrade edges")
Expand Down Expand Up @@ -337,6 +269,84 @@ func TestClusterExtensionInstallSuccessorVersion(t *testing.T) {
}, pollDuration, pollInterval)
}

func TestClusterExtensionInstallReResolvesWhenNewCatalog(t *testing.T) {
t.Log("When a cluster extension is installed from a catalog")
t.Log("It resolves again when a new catalog is available")

// Tag the image with the new tag
var err error
v1Image := fmt.Sprintf("%s/%s", os.Getenv("CLUSTER_REGISTRY_HOST"), os.Getenv("E2E_TEST_CATALOG_V1"))
err = crane.Tag(v1Image, LatestImageTag, crane.Insecure)
require.NoError(t, err)

// create a test-catalog with latest image tag
latestCatalogImage := fmt.Sprintf("%s/e2e/test-catalog:latest", os.Getenv("LOCAL_REGISTRY_HOST"))
extensionCatalog, err := createTestCatalog(context.Background(), testCatalogName, latestCatalogImage)
require.NoError(t, err)
clusterExtensionName := fmt.Sprintf("clusterextension-%s", rand.String(8))
clusterExtension := &ocv1alpha1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{
Name: clusterExtensionName,
},
}
defer testCleanup(t, extensionCatalog, clusterExtension)
defer getArtifactsOutput(t)

clusterExtension.Spec = ocv1alpha1.ClusterExtensionSpec{
PackageName: "prometheus",
InstallNamespace: "default",
ServiceAccount: ocv1alpha1.ServiceAccountReference{
Name: "default",
},
}
t.Log("It resolves the specified package with correct bundle path")
t.Log("By creating the ClusterExtension resource")
require.NoError(t, c.Create(context.Background(), clusterExtension))

t.Log("By reporting a successful resolution and bundle path")
require.EventuallyWithT(t, func(ct *assert.CollectT) {
assert.NoError(ct, c.Get(context.Background(), types.NamespacedName{Name: clusterExtension.Name}, clusterExtension))
assert.Len(ct, clusterExtension.Status.Conditions, len(conditionsets.ConditionTypes))
cond := apimeta.FindStatusCondition(clusterExtension.Status.Conditions, ocv1alpha1.TypeResolved)
if !assert.NotNil(ct, cond) {
return
}
assert.Equal(ct, metav1.ConditionTrue, cond.Status)
assert.Equal(ct, ocv1alpha1.ReasonSuccess, cond.Reason)
assert.Contains(ct, cond.Message, "resolved to")
assert.Equal(ct, &ocv1alpha1.BundleMetadata{Name: "prometheus-operator.1.2.0", Version: "1.2.0"}, clusterExtension.Status.ResolvedBundle)
}, pollDuration, pollInterval)

// update tag on test-catalog image with v2 image
t.Log("By updating the catalog tag to point to the v2 catalog")
v2Image := fmt.Sprintf("%s/%s", os.Getenv("CLUSTER_REGISTRY_HOST"), os.Getenv("E2E_TEST_CATALOG_V2"))
err = crane.Tag(v2Image, LatestImageTag, crane.Insecure)
require.NoError(t, err)
require.EventuallyWithT(t, func(ct *assert.CollectT) {
assert.NoError(ct, c.Get(context.Background(), types.NamespacedName{Name: extensionCatalog.Name}, extensionCatalog))
cond := apimeta.FindStatusCondition(extensionCatalog.Status.Conditions, catalogd.TypeUnpacked)
if !assert.NotNil(ct, cond) {
return
}
assert.Equal(ct, metav1.ConditionTrue, cond.Status)
assert.Equal(ct, catalogd.ReasonUnpackSuccessful, cond.Reason)
}, pollDuration, pollInterval)

t.Log("By eventually reporting a successful resolution and bundle path")
require.EventuallyWithT(t, func(ct *assert.CollectT) {
assert.NoError(ct, c.Get(context.Background(), types.NamespacedName{Name: clusterExtension.Name}, clusterExtension))
assert.Len(ct, clusterExtension.Status.Conditions, len(conditionsets.ConditionTypes))
cond := apimeta.FindStatusCondition(clusterExtension.Status.Conditions, ocv1alpha1.TypeResolved)
if !assert.NotNil(ct, cond) {
return
}
assert.Equal(ct, metav1.ConditionTrue, cond.Status)
assert.Equal(ct, ocv1alpha1.ReasonSuccess, cond.Reason)
assert.Contains(ct, cond.Message, "resolved to")
assert.Equal(ct, &ocv1alpha1.BundleMetadata{Name: "prometheus-operator.2.0.0", Version: "2.0.0"}, clusterExtension.Status.ResolvedBundle)
}, pollDuration, pollInterval)
}

// getArtifactsOutput gets all the artifacts from the test run and saves them to the artifact path.
// Currently it saves:
// - clusterextensions
Expand Down
3 changes: 3 additions & 0 deletions test/e2e/e2e_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"os"
"testing"
"time"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
Expand All @@ -24,6 +25,7 @@ var (
const (
testCatalogRefEnvVar = "CATALOG_IMG"
testCatalogName = "test-catalog"
LatestImageTag = "latest"
)

func TestMain(m *testing.M) {
Expand All @@ -50,6 +52,7 @@ func createTestCatalog(ctx context.Context, name string, imageRef string) (*cata
Image: &catalogd.ImageSource{
Ref: imageRef,
InsecureSkipTLSVerify: true,
PollInterval: &metav1.Duration{Duration: time.Second},
},
},
},
Expand Down
8 changes: 4 additions & 4 deletions test/extension-developer-e2e/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ a KinD cluster with the name specified in the arguments.
The following environment variables are required for configuring this script:
- \$CATALOG_IMG - the tag for the catalog image that contains the registry+v1 bundle.
- \$REG_PKG_NAME - the name of the package for the extension that uses the registry+v1 bundle format.
- \$REGISTRY_ROOT - hostname:port of the local docker-registry
- \$LOCAL_REGISTRY_HOST - hostname:port of the local docker-registry
setup.sh also takes 5 arguments.
Usage:
Expand Down Expand Up @@ -42,8 +42,8 @@ if [[ -z "${REG_PKG_NAME}" ]]; then
exit 1
fi

if [[ -z "${REGISTRY_ROOT}" ]]; then
echo "\$REGISTRY_ROOT is required to be set"
if [[ -z "${LOCAL_REGISTRY_HOST}" ]]; then
echo "\$LOCAL_REGISTRY_HOST is required to be set"
echo "${help}"
exit 1
fi
Expand All @@ -69,7 +69,7 @@ kcluster_name=$5
namespace=$6

reg_img="${DOMAIN}/registry:v0.0.1"
reg_bundle_img="${REGISTRY_ROOT}/bundles/registry-v1/registry-bundle:v0.0.1"
reg_bundle_img="${LOCAL_REGISTRY_HOST}/bundles/registry-v1/registry-bundle:v0.0.1"

catalog_img="${CATALOG_IMG}"
reg_pkg_name="${REG_PKG_NAME}"
Expand Down
29 changes: 15 additions & 14 deletions test/tools/build-push-e2e-catalog.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,45 +21,46 @@ if [[ "$#" -ne 2 ]]; then
fi

namespace=$1
tag=$2
image=$2
tag=${image##*:}

echo "${namespace}" "${tag}"
echo "${namespace}" "${image}" "${tag}"

kubectl create configmap -n "${namespace}" --from-file=testdata/catalogs/test-catalog.Dockerfile operator-controller-e2e.dockerfile
kubectl create configmap -n "${namespace}" --from-file=testdata/catalogs/test-catalog operator-controller-e2e.build-contents
kubectl create configmap -n "${namespace}" --from-file=testdata/catalogs/test-catalog-${tag}.Dockerfile operator-controller-e2e-${tag}.dockerfile
kubectl create configmap -n "${namespace}" --from-file=testdata/catalogs/test-catalog-${tag} operator-controller-e2e-${tag}.build-contents

kubectl apply -f - << EOF
apiVersion: batch/v1
kind: Job
metadata:
name: kaniko
name: "kaniko-${tag}"
namespace: "${namespace}"
spec:
template:
spec:
containers:
- name: kaniko
- name: kaniko-${tag}
image: gcr.io/kaniko-project/executor:latest
args: ["--dockerfile=/workspace/test-catalog.Dockerfile",
args: ["--dockerfile=/workspace/test-catalog-${tag}.Dockerfile",
"--context=/workspace/",
"--destination=${tag}",
"--destination=${image}",
"--skip-tls-verify"]
volumeMounts:
- name: dockerfile
mountPath: /workspace/
- name: build-contents
mountPath: /workspace/test-catalog/
mountPath: /workspace/test-catalog-${tag}/
restartPolicy: Never
volumes:
- name: dockerfile
configMap:
name: operator-controller-e2e.dockerfile
name: operator-controller-e2e-${tag}.dockerfile
items:
- key: test-catalog.Dockerfile
path: test-catalog.Dockerfile
- key: test-catalog-${tag}.Dockerfile
path: test-catalog-${tag}.Dockerfile
- name: build-contents
configMap:
name: operator-controller-e2e.build-contents
name: operator-controller-e2e-${tag}.build-contents
EOF

kubectl wait --for=condition=Complete -n "${namespace}" jobs/kaniko --timeout=60s
kubectl wait --for=condition=Complete -n "${namespace}" jobs/kaniko-${tag} --timeout=60s
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
FROM scratch
ADD test-catalog /configs
ADD test-catalog-v1 /configs

# Set DC-specific label for the location of the DC root directory
# in the image
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ entries:
replaces: prometheus-operator.1.0.0
- name: prometheus-operator.1.2.0
replaces: prometheus-operator.1.0.1
- name: prometheus-operator.2.0.0
replaces: prometheus-operator.1.2.0
---
schema: olm.bundle
name: prometheus-operator.1.0.0
Expand Down Expand Up @@ -50,13 +48,3 @@ properties:
value:
packageName: prometheus
version: 1.2.0
---
schema: olm.bundle
name: prometheus-operator.2.0.0
package: prometheus
image: docker-registry.operator-controller-e2e.svc.cluster.local:5000/bundles/registry-v1/prometheus-operator:v2.0.0
properties:
- type: olm.package
value:
packageName: prometheus
version: 2.0.0
6 changes: 6 additions & 0 deletions testdata/catalogs/test-catalog-v2.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM scratch
ADD test-catalog-v2 /configs

# Set DC-specific label for the location of the DC root directory
# in the image
LABEL operators.operatorframework.io.index.configs.v1=/configs
2 changes: 2 additions & 0 deletions testdata/catalogs/test-catalog-v2/.indexignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/expected_all.json
..*
Loading

0 comments on commit c0e9639

Please sign in to comment.