Skip to content

Commit 7446060

Browse files
perdasilvaPer Goncalves da Silva
and
Per Goncalves da Silva
authored
🐛 mitigate upgrade-e2e test flakiness (operator-framework#1627)
* add artifact collection to upgrade-e2e-tests Signed-off-by: Per Goncalves da Silva <[email protected]> * mitigate upgrade-e2e flakiness Signed-off-by: Per Goncalves da Silva <[email protected]> --------- Signed-off-by: Per Goncalves da Silva <[email protected]> Co-authored-by: Per Goncalves da Silva <[email protected]>
1 parent c8380d2 commit 7446060

File tree

5 files changed

+236
-178
lines changed

5 files changed

+236
-178
lines changed

.github/workflows/e2e.yaml

+7-1
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,10 @@ jobs:
5858
go-version-file: go.mod
5959

6060
- name: Run the upgrade e2e test
61-
run: make test-upgrade-e2e
61+
run: ARTIFACT_PATH=/tmp/artifacts make test-upgrade-e2e
62+
63+
- uses: cytopia/[email protected]
64+
if: failure()
65+
with:
66+
name: upgrade-e2e-artifacts
67+
path: /tmp/artifacts/

test/e2e/cluster_extension_install_test.go

+11-145
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,13 @@ package e2e
33
import (
44
"context"
55
"fmt"
6-
"io"
76
"os"
8-
"path/filepath"
9-
"strings"
107
"testing"
118
"time"
129

1310
"github.com/google/go-containerregistry/pkg/crane"
1411
"github.com/stretchr/testify/assert"
1512
"github.com/stretchr/testify/require"
16-
"gopkg.in/yaml.v2"
17-
appsv1 "k8s.io/api/apps/v1"
1813
corev1 "k8s.io/api/core/v1"
1914
rbacv1 "k8s.io/api/rbac/v1"
2015
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
@@ -24,12 +19,11 @@ import (
2419
"k8s.io/apimachinery/pkg/labels"
2520
"k8s.io/apimachinery/pkg/types"
2621
"k8s.io/apimachinery/pkg/util/rand"
27-
kubeclient "k8s.io/client-go/kubernetes"
28-
"k8s.io/utils/env"
2922
"sigs.k8s.io/controller-runtime/pkg/client"
3023

3124
ocv1 "github.com/operator-framework/operator-controller/api/v1"
3225
catalogd "github.com/operator-framework/operator-controller/catalogd/api/v1"
26+
"github.com/operator-framework/operator-controller/test/utils"
3327
)
3428

3529
const (
@@ -306,7 +300,7 @@ func TestClusterExtensionInstallRegistry(t *testing.T) {
306300

307301
clusterExtension, extensionCatalog, sa, ns := testInit(t)
308302
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
309-
defer getArtifactsOutput(t)
303+
defer utils.CollectTestArtifacts(t, artifactName, c, cfg)
310304

311305
clusterExtension.Spec = ocv1.ClusterExtensionSpec{
312306
Source: ocv1.SourceConfig{
@@ -366,7 +360,7 @@ func TestClusterExtensionInstallRegistryDynamic(t *testing.T) {
366360

367361
clusterExtension, extensionCatalog, sa, ns := testInit(t)
368362
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
369-
defer getArtifactsOutput(t)
363+
defer utils.CollectTestArtifacts(t, artifactName, c, cfg)
370364

371365
clusterExtension.Spec = ocv1.ClusterExtensionSpec{
372366
Source: ocv1.SourceConfig{
@@ -441,7 +435,7 @@ func TestClusterExtensionInstallRegistryMultipleBundles(t *testing.T) {
441435
require.NoError(t, err)
442436

443437
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
444-
defer getArtifactsOutput(t)
438+
defer utils.CollectTestArtifacts(t, artifactName, c, cfg)
445439
defer func(cat *catalogd.ClusterCatalog) {
446440
require.NoError(t, c.Delete(context.Background(), cat))
447441
require.Eventually(t, func() bool {
@@ -489,7 +483,7 @@ func TestClusterExtensionBlockInstallNonSuccessorVersion(t *testing.T) {
489483

490484
clusterExtension, extensionCatalog, sa, ns := testInit(t)
491485
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
492-
defer getArtifactsOutput(t)
486+
defer utils.CollectTestArtifacts(t, artifactName, c, cfg)
493487

494488
t.Log("By creating an ClusterExtension at a specified version")
495489
clusterExtension.Spec = ocv1.ClusterExtensionSpec{
@@ -552,7 +546,7 @@ func TestClusterExtensionForceInstallNonSuccessorVersion(t *testing.T) {
552546

553547
clusterExtension, extensionCatalog, sa, ns := testInit(t)
554548
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
555-
defer getArtifactsOutput(t)
549+
defer utils.CollectTestArtifacts(t, artifactName, c, cfg)
556550

557551
t.Log("By creating an ClusterExtension at a specified version")
558552
clusterExtension.Spec = ocv1.ClusterExtensionSpec{
@@ -601,7 +595,7 @@ func TestClusterExtensionInstallSuccessorVersion(t *testing.T) {
601595
t.Log("When resolving upgrade edges")
602596
clusterExtension, extensionCatalog, sa, ns := testInit(t)
603597
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
604-
defer getArtifactsOutput(t)
598+
defer utils.CollectTestArtifacts(t, artifactName, c, cfg)
605599

606600
t.Log("By creating an ClusterExtension at a specified version")
607601
clusterExtension.Spec = ocv1.ClusterExtensionSpec{
@@ -649,7 +643,7 @@ func TestClusterExtensionInstallReResolvesWhenCatalogIsPatched(t *testing.T) {
649643
t.Log("It resolves again when a catalog is patched with new ImageRef")
650644
clusterExtension, extensionCatalog, sa, ns := testInit(t)
651645
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
652-
defer getArtifactsOutput(t)
646+
defer utils.CollectTestArtifacts(t, artifactName, c, cfg)
653647

654648
clusterExtension.Spec = ocv1.ClusterExtensionSpec{
655649
Source: ocv1.SourceConfig{
@@ -736,7 +730,7 @@ func TestClusterExtensionInstallReResolvesWhenNewCatalog(t *testing.T) {
736730
sa, err := createServiceAccount(context.Background(), types.NamespacedName{Name: clusterExtensionName, Namespace: ns.Name}, clusterExtensionName)
737731
require.NoError(t, err)
738732
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
739-
defer getArtifactsOutput(t)
733+
defer utils.CollectTestArtifacts(t, artifactName, c, cfg)
740734

741735
clusterExtension.Spec = ocv1.ClusterExtensionSpec{
742736
Source: ocv1.SourceConfig{
@@ -797,7 +791,7 @@ func TestClusterExtensionInstallReResolvesWhenManagedContentChanged(t *testing.T
797791
t.Log("It resolves again when managed content is changed")
798792
clusterExtension, extensionCatalog, sa, ns := testInit(t)
799793
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
800-
defer getArtifactsOutput(t)
794+
defer utils.CollectTestArtifacts(t, artifactName, c, cfg)
801795

802796
clusterExtension.Spec = ocv1.ClusterExtensionSpec{
803797
Source: ocv1.SourceConfig{
@@ -860,7 +854,7 @@ func TestClusterExtensionRecoversFromInitialInstallFailedWhenFailureFixed(t *tes
860854
err := c.Create(context.Background(), sa)
861855
require.NoError(t, err)
862856
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
863-
defer getArtifactsOutput(t)
857+
defer utils.CollectTestArtifacts(t, artifactName, c, cfg)
864858

865859
clusterExtension.Spec = ocv1.ClusterExtensionSpec{
866860
Source: ocv1.SourceConfig{
@@ -936,131 +930,3 @@ func TestClusterExtensionRecoversFromInitialInstallFailedWhenFailureFixed(t *tes
936930
}
937931
}, pollDuration, pollInterval)
938932
}
939-
940-
// getArtifactsOutput gets all the artifacts from the test run and saves them to the artifact path.
941-
// Currently it saves:
942-
// - clusterextensions
943-
// - pods logs
944-
// - deployments
945-
// - catalogsources
946-
func getArtifactsOutput(t *testing.T) {
947-
basePath := env.GetString("ARTIFACT_PATH", "")
948-
if basePath == "" {
949-
return
950-
}
951-
952-
kubeClient, err := kubeclient.NewForConfig(cfg)
953-
require.NoError(t, err)
954-
955-
// sanitize the artifact name for use as a directory name
956-
testName := strings.ReplaceAll(strings.ToLower(t.Name()), " ", "-")
957-
// Get the test description and sanitize it for use as a directory name
958-
artifactPath := filepath.Join(basePath, artifactName, fmt.Sprint(time.Now().UnixNano()), testName)
959-
960-
// Create the full artifact path
961-
err = os.MkdirAll(artifactPath, 0755)
962-
require.NoError(t, err)
963-
964-
// Get all namespaces
965-
namespaces := corev1.NamespaceList{}
966-
if err := c.List(context.Background(), &namespaces); err != nil {
967-
fmt.Printf("Failed to list namespaces: %v", err)
968-
}
969-
970-
// get all cluster extensions save them to the artifact path.
971-
clusterExtensions := ocv1.ClusterExtensionList{}
972-
if err := c.List(context.Background(), &clusterExtensions, client.InNamespace("")); err != nil {
973-
fmt.Printf("Failed to list cluster extensions: %v", err)
974-
}
975-
for _, clusterExtension := range clusterExtensions.Items {
976-
// Save cluster extension to artifact path
977-
clusterExtensionYaml, err := yaml.Marshal(clusterExtension)
978-
if err != nil {
979-
fmt.Printf("Failed to marshal cluster extension: %v", err)
980-
continue
981-
}
982-
if err := os.WriteFile(filepath.Join(artifactPath, clusterExtension.Name+"-clusterextension.yaml"), clusterExtensionYaml, 0600); err != nil {
983-
fmt.Printf("Failed to write cluster extension to file: %v", err)
984-
}
985-
}
986-
987-
// get all catalogsources save them to the artifact path.
988-
catalogsources := catalogd.ClusterCatalogList{}
989-
if err := c.List(context.Background(), &catalogsources, client.InNamespace("")); err != nil {
990-
fmt.Printf("Failed to list catalogsources: %v", err)
991-
}
992-
for _, catalogsource := range catalogsources.Items {
993-
// Save catalogsource to artifact path
994-
catalogsourceYaml, err := yaml.Marshal(catalogsource)
995-
if err != nil {
996-
fmt.Printf("Failed to marshal catalogsource: %v", err)
997-
continue
998-
}
999-
if err := os.WriteFile(filepath.Join(artifactPath, catalogsource.Name+"-catalogsource.yaml"), catalogsourceYaml, 0600); err != nil {
1000-
fmt.Printf("Failed to write catalogsource to file: %v", err)
1001-
}
1002-
}
1003-
1004-
for _, namespace := range namespaces.Items {
1005-
// let's ignore kube-* namespaces.
1006-
if strings.Contains(namespace.Name, "kube-") {
1007-
continue
1008-
}
1009-
1010-
namespacedArtifactPath := filepath.Join(artifactPath, namespace.Name)
1011-
if err := os.Mkdir(namespacedArtifactPath, 0755); err != nil {
1012-
fmt.Printf("Failed to create namespaced artifact path: %v", err)
1013-
continue
1014-
}
1015-
1016-
// get all deployments in the namespace and save them to the artifact path.
1017-
deployments := appsv1.DeploymentList{}
1018-
if err := c.List(context.Background(), &deployments, client.InNamespace(namespace.Name)); err != nil {
1019-
fmt.Printf("Failed to list deployments %v in namespace: %q", err, namespace.Name)
1020-
continue
1021-
}
1022-
1023-
for _, deployment := range deployments.Items {
1024-
// Save deployment to artifact path
1025-
deploymentYaml, err := yaml.Marshal(deployment)
1026-
if err != nil {
1027-
fmt.Printf("Failed to marshal deployment: %v", err)
1028-
continue
1029-
}
1030-
if err := os.WriteFile(filepath.Join(namespacedArtifactPath, deployment.Name+"-deployment.yaml"), deploymentYaml, 0600); err != nil {
1031-
fmt.Printf("Failed to write deployment to file: %v", err)
1032-
}
1033-
}
1034-
1035-
// Get logs from all pods in all namespaces
1036-
pods := corev1.PodList{}
1037-
if err := c.List(context.Background(), &pods, client.InNamespace(namespace.Name)); err != nil {
1038-
fmt.Printf("Failed to list pods %v in namespace: %q", err, namespace.Name)
1039-
}
1040-
for _, pod := range pods.Items {
1041-
if pod.Status.Phase != corev1.PodRunning && pod.Status.Phase != corev1.PodSucceeded && pod.Status.Phase != corev1.PodFailed {
1042-
continue
1043-
}
1044-
for _, container := range pod.Spec.Containers {
1045-
logs, err := kubeClient.CoreV1().Pods(namespace.Name).GetLogs(pod.Name, &corev1.PodLogOptions{Container: container.Name}).Stream(context.Background())
1046-
if err != nil {
1047-
fmt.Printf("Failed to get logs for pod %q in namespace %q: %v", pod.Name, namespace.Name, err)
1048-
continue
1049-
}
1050-
defer logs.Close()
1051-
1052-
outFile, err := os.Create(filepath.Join(namespacedArtifactPath, pod.Name+"-"+container.Name+"-logs.txt"))
1053-
if err != nil {
1054-
fmt.Printf("Failed to create file for pod %q in namespace %q: %v", pod.Name, namespace.Name, err)
1055-
continue
1056-
}
1057-
defer outFile.Close()
1058-
1059-
if _, err := io.Copy(outFile, logs); err != nil {
1060-
fmt.Printf("Failed to copy logs for pod %q in namespace %q: %v", pod.Name, namespace.Name, err)
1061-
continue
1062-
}
1063-
}
1064-
}
1065-
}
1066-
}

0 commit comments

Comments
 (0)