Skip to content

Commit

Permalink
fix: explicit cleanup of eks clusters and using static identity as well
Browse files Browse the repository at this point in the history
The EKS e2e tests where timing out on cleanup. The tests have been
changed in the following way:

* Explicit cluster deletion as part of the test instead of relying on
the suite cleanup
* Changed templates used by the tests to use AWSClusterStaticIdentity
and added shared functions to create an instance of this CR and also the
associated secrets

Signed-off-by: Richard Case <richard@weave.works>
  • Loading branch information
richardcase committed Jun 17, 2021
1 parent daec13d commit 7f14d22
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 13 deletions.
1 change: 1 addition & 0 deletions test/e2e/data/e2e_conf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,4 @@ intervals:
default/wait-infra-subnets: ["5m", "30s"]
default/wait-machine-pool-nodes: ["40m", "10s"]
default/wait-machine-pool-upgrade: [ "50m", "10s" ]
default/wait-create-identity: ["1m", "10s"]
4 changes: 3 additions & 1 deletion test/e2e/data/e2e_eks_conf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,14 @@ variables:
EXP_EKS_ADD_ROLES: "false"
VPC_ADDON_VERSION: "v1.6.3-eksbuild.1"
CONFORMANCE_CI_ARTIFACTS_KUBERNETES_VERSION: "v1.19.8"
AUTO_CONTROLLER_IDENTITY_CREATOR: "false"

intervals:
default/wait-cluster: ["30m", "10s"]
default/wait-control-plane: ["30m", "10s"]
default/wait-worker-nodes: ["30m", "10s"]
default/wait-controllers: ["3m", "10s"]
default/wait-delete-cluster: ["35m", "10s"]
default/wait-delete-cluster: ["35m", "30s"]
default/wait-delete-machine: ["10m", "10s"]
default/wait-delete-machine-deployment: ["10m", "10s"]
default/wait-delete-machine-pool: ["20m", "10s"]
Expand All @@ -146,3 +147,4 @@ intervals:
default/wait-infra-subnets: ["5m", "30s"]
default/wait-control-plane-upgrade: ["35m", "30s"]
default/wait-addon-status: ["10m", "30s"]
default/wait-create-identity: ["1m", "10s"]
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@ spec:
- name: "vpc-cni"
version: "${VPC_ADDON_VERSION}"
conflictResolution: "overwrite"
identityRef:
kind: AWSClusterStaticIdentity
name: e2e-account
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ spec:
region: "${AWS_REGION}"
sshKeyName: "${AWS_SSH_KEY_NAME}"
version: "${KUBERNETES_VERSION}"
identityRef:
kind: AWSClusterStaticIdentity
name: e2e-account
4 changes: 3 additions & 1 deletion test/e2e/shared/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,12 @@ func DumpSpecResourcesAndCleanup(ctx context.Context, specName string, namespace
Byf("Dumping all EC2 instances in the %q namespace", namespace.Name)
DumpMachines(ctx, e2eCtx, namespace)
if !e2eCtx.Settings.SkipCleanup {
intervals := e2eCtx.E2EConfig.GetIntervals(specName, "wait-delete-cluster")
Byf("Deleting all clusters in the %q namespace with intervals %q", namespace.Name, intervals)
framework.DeleteAllClustersAndWait(ctx, framework.DeleteAllClustersAndWaitInput{
Client: e2eCtx.Environment.BootstrapClusterProxy.GetClient(),
Namespace: namespace.Name,
}, e2eCtx.E2EConfig.GetIntervals(specName, "wait-delete-cluster")...)
}, intervals...)

Byf("Deleting namespace used for hosting the %q test spec", specName)
framework.DeleteNamespace(ctx, framework.DeleteNamespaceInput{
Expand Down
120 changes: 120 additions & 0 deletions test/e2e/shared/identity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// +build e2e

/*
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package shared

import (
"context"

. "github.com/onsi/gomega"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

infrav1 "sigs.k8s.io/cluster-api-provider-aws/api/v1alpha4"
)

const (
credsSecretName = "e2e-account-creds"
capaNamespace = "capa-system"
eksNamespace = "capa-eks-control-plane-system"
idName = "e2e-account"
)

func SetupStaticCredentials(ctx context.Context, namespace *corev1.Namespace, e2eCtx *E2EContext) {
Expect(ctx).NotTo(BeNil(), "ctx is required for SetupStaticCredentials")
Expect(namespace).NotTo(BeNil(), "namespace is required for SetupStaticCredentials")
Expect(e2eCtx).NotTo(BeNil(), "e2eCtx is required for SetupStaticCredentials")
Expect(e2eCtx.Environment.BootstrapAccessKey).NotTo(BeNil(), "e2eCtx.Environment.BootstrapAccessKey is required for SetupStaticCredentials")

secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: credsSecretName,
Namespace: capaNamespace,
},
StringData: map[string]string{
"AccessKeyID": *e2eCtx.Environment.BootstrapAccessKey.AccessKeyId,
"SecretAccessKey": *e2eCtx.Environment.BootstrapAccessKey.SecretAccessKey,
},
}

client := e2eCtx.Environment.BootstrapClusterProxy.GetClient()
Byf("Creating credentials secret %s in namespace %s", secret.Name, secret.Namespace)
Eventually(func() error {
return client.Create(ctx, secret)
}, e2eCtx.E2EConfig.GetIntervals("", "wait-create-identity")...).Should(Succeed())

if e2eCtx.IsManaged {
//TODO: this doesn't feel right to be creating the secret in 2 places.
cpSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: credsSecretName,
Namespace: eksNamespace,
},
StringData: map[string]string{
"AccessKeyID": *e2eCtx.Environment.BootstrapAccessKey.AccessKeyId,
"SecretAccessKey": *e2eCtx.Environment.BootstrapAccessKey.SecretAccessKey,
},
}
Byf("Creating credentials secret %s in namespace %s", cpSecret.Name, cpSecret.Namespace)
Eventually(func() error {
return client.Create(ctx, cpSecret)
}, e2eCtx.E2EConfig.GetIntervals("", "wait-create-identity")...).Should(Succeed())
}

id := &infrav1.AWSClusterStaticIdentity{
ObjectMeta: metav1.ObjectMeta{
Name: idName,
Namespace: namespace.Name,
},
Spec: infrav1.AWSClusterStaticIdentitySpec{
SecretRef: credsSecretName,
AWSClusterIdentitySpec: infrav1.AWSClusterIdentitySpec{
AllowedNamespaces: &infrav1.AllowedNamespaces{
NamespaceList: []string{namespace.Name},
},
},
},
}

Byf("Creating AWSClusterStaticIdentity %s in namespace %s", id.Name, namespace.Name)
Eventually(func() error {
return client.Create(ctx, id)
}, e2eCtx.E2EConfig.GetIntervals("", "wait-create-identity")...).Should(Succeed())
}

func CleanupStaticCredentials(ctx context.Context, namespace *corev1.Namespace, e2eCtx *E2EContext) {
Expect(ctx).NotTo(BeNil(), "ctx is required for SetupStaticCredentials")
Expect(namespace).NotTo(BeNil(), "namespace is required for SetupStaticCredentials")
Expect(e2eCtx).NotTo(BeNil(), "e2eCtx is required for SetupStaticCredentials")

id := &infrav1.AWSClusterStaticIdentity{
ObjectMeta: metav1.ObjectMeta{
Name: idName,
Namespace: namespace.Name,
},
}

Byf("Deleting AWSClusterStaticIdentity %s in namespace %s", idName, namespace.Name)
client := e2eCtx.Environment.BootstrapClusterProxy.GetClient()
Eventually(func() error {
return client.Delete(ctx, id)
}, e2eCtx.E2EConfig.GetIntervals("", "wait-create-identity")...).Should(Succeed())

//NOTE: secrets should be cleared up when the namespaces are deleted
}
7 changes: 5 additions & 2 deletions test/e2e/shared/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@ package shared
import (
"context"
"flag"
"github.com/gofrs/flock"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"time"

"github.com/gofrs/flock"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

Expand Down Expand Up @@ -137,7 +138,9 @@ func Node1BeforeSuite(e2eCtx *E2EContext) []byte {
e2eCtx.BootstratpUserAWSSession = NewAWSSessionWithKey(e2eCtx.Environment.BootstrapAccessKey)

// Image ID is needed when using a CI Kubernetes version. This is used in conformance test and upgrade to main test.
e2eCtx.E2EConfig.Variables["IMAGE_ID"] = conformanceImageID(e2eCtx)
if !e2eCtx.IsManaged {
e2eCtx.E2EConfig.Variables["IMAGE_ID"] = conformanceImageID(e2eCtx)
}

Byf("Creating a clusterctl local repository into %q", e2eCtx.Settings.ArtifactFolder)
e2eCtx.Environment.ClusterctlConfigPath = createClusterctlLocalRepository(e2eCtx.E2EConfig, filepath.Join(e2eCtx.Settings.ArtifactFolder, "repository"))
Expand Down
31 changes: 22 additions & 9 deletions test/e2e/suites/managed/eks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
. "github.com/onsi/gomega"

corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/cluster-api/test/framework"
"sigs.k8s.io/cluster-api/util"

controlplanev1 "sigs.k8s.io/cluster-api-provider-aws/controlplane/eks/api/v1alpha4"
Expand Down Expand Up @@ -53,6 +54,9 @@ var _ = Describe("EKS cluster tests", func() {
namespace = shared.SetupSpecNamespace(ctx, specName, e2eCtx)
clusterName = fmt.Sprintf("cluster-%s", util.RandomString(6))

By("setting up AWS statis credentials")
shared.SetupStaticCredentials(ctx, namespace, e2eCtx)

By("default iam role should exist")
verifyRoleExistsAndOwned(controlplanev1.DefaultEKSControlPlaneRole, clusterName, false, e2eCtx.BootstratpUserAWSSession)

Expand Down Expand Up @@ -113,15 +117,24 @@ var _ = Describe("EKS cluster tests", func() {
}
})

shared.Byf("should delete cluster %s", clusterName)
DeleteClusterSpec(ctx, func() DeleteClusterSpecInput {
return DeleteClusterSpecInput{
E2EConfig: e2eCtx.E2EConfig,
BootstrapClusterProxy: e2eCtx.Environment.BootstrapClusterProxy,
ClusterName: clusterName,
Namespace: namespace,
}
shared.Byf("getting cluster with name %s", clusterName)
cluster := framework.GetClusterByName(ctx, framework.GetClusterByNameInput{
Getter: e2eCtx.Environment.BootstrapClusterProxy.GetClient(),
Namespace: namespace.Name,
Name: clusterName,
})
})
Expect(cluster).NotTo(BeNil(), "couldn't find CAPI cluster")

framework.DeleteCluster(ctx, framework.DeleteClusterInput{
Deleter: e2eCtx.Environment.BootstrapClusterProxy.GetClient(),
Cluster: cluster,
})
framework.WaitForClusterDeleted(ctx, framework.WaitForClusterDeletedInput{
Getter: e2eCtx.Environment.BootstrapClusterProxy.GetClient(),
Cluster: cluster,
}, e2eCtx.E2EConfig.GetIntervals("", "wait-delete-cluster")...)

By("Deleting AWS static credentials")
shared.CleanupStaticCredentials(ctx, namespace, e2eCtx)
})
})

0 comments on commit 7f14d22

Please sign in to comment.