Skip to content

Commit

Permalink
E2E: plugin group life cycle e2e test cases and e2e framework tooling (
Browse files Browse the repository at this point in the history
…#132)

implementation

Co-authored-by: Chandra Pamuluri <[email protected]>
  • Loading branch information
chandrareddyp and Chandra Pamuluri authored Apr 10, 2023
1 parent 8c03241 commit 70755fd
Show file tree
Hide file tree
Showing 22 changed files with 944 additions and 186 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ test: fmt ## Run Tests
.PHONY: e2e-cli-core ## Execute all CLI Core E2E Tests
e2e-cli-core: e2e-cli-plugin-compatibility-test e2e-cli-tmc-test e2e-cli-plugin-lifecycle-test
export TANZU_CLI_CEIP_OPT_IN_PROMPT_ANSWER="Yes" ; \
${GO} test `go list ./test/e2e/... | grep -v test/e2e/context/tmc | grep -v test/e2e/plugins_compatibility | grep -v test/e2e/plugin_lifecycle` -timeout 60m -race -coverprofile coverage.txt ${GOTEST_VERBOSE}
${GO} test `go list ./test/e2e/... | grep -v test/e2e/context/tmc | grep -v test/e2e/plugins_compatibility | grep -v test/e2e/plugin_lifecycle | grep -v test/e2e/plugin_sync` -timeout 60m -race -coverprofile coverage.txt ${GOTEST_VERBOSE}

.PHONY: e2e-cli-plugin-compatibility-test ## Execute CLI Core Plugin Compatibility E2E test cases
e2e-cli-plugin-compatibility-test:
Expand All @@ -213,6 +213,7 @@ e2e-cli-plugin-lifecycle-test:
export TANZU_CLI_PLUGIN_DISCOVERY_IMAGE_SIGNATURE_VERIFICATION_SKIP_LIST=$(TANZU_CLI_E2E_TEST_LOCAL_CENTRAL_REPO_URL) ; \
export TANZU_CLI_CEIP_OPT_IN_PROMPT_ANSWER="Yes" ; \
${GO} test ./test/e2e/plugin_lifecycle -timeout 60m -race -coverprofile coverage.txt ${GOTEST_VERBOSE} ; \
${GO} test ./test/e2e/plugin_sync -timeout 60m -race -coverprofile coverage.txt ${GOTEST_VERBOSE} ; \
fi

.PHONY: e2e-cli-tmc-test ## Execute CLI Core TMC Specific E2E test cases
Expand Down
19 changes: 15 additions & 4 deletions test/e2e/config/config_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ const ContextNameConfigPrefix = "config-k8s-"
// tests the 'tanzu config server list' and 'tanzu config server delete' commands
var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:Config-Server]", func() {
Context("tanzu config server command test cases ", func() {
// Test case: delete config files and initialize config
It("should initialize configuration successfully", func() {
// delete config files
err := tf.Config.DeleteCLIConfigurationFiles()
Expect(err).To(BeNil())
// call init
err = tf.Config.ConfigInit()
Expect(err).To(BeNil())
// should create config files
Expect(tf.Config.IsCLIConfigurationFilesExists()).To(BeTrue())
})
// Test case: delete servers if any exists, with command 'tanzu config server delete'
It("list and delete servers if any exists before running tests", func() {
By("delete servers if any exists before running tests")
Expand All @@ -36,18 +47,18 @@ var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:Config-Server]", func() {
It("create context with kubeconfig and context", func() {
By("create context with kubeconfig and context")
ctxName := ContextNameConfigPrefix + framework.RandomString(4)
err := tf.ContextCmd.CreateContextWithKubeconfig(ctxName, clusterInfo.KubeConfigPath, clusterInfo.ClusterContext)
err := tf.ContextCmd.CreateContextWithKubeconfig(ctxName, clusterInfo.KubeConfigPath, clusterInfo.ClusterKubeContext)
Expect(err).To(BeNil(), "context should create without any error")
Expect(context.IsContextExists(tf, ctxName)).To(BeTrue(), "context should be available")
Expect(framework.IsContextExists(tf, ctxName)).To(BeTrue(), "context should be available")
contextNames = append(contextNames, ctxName)
})
// Test case: Create context for k8s target with "default" kubeconfig and its context only as input value
It("create context with default kubeconfig and context", func() {
By("create context with default kubeconfig and context")
ctxName := "context-defaultConfig-" + framework.RandomString(4)
err := tf.ContextCmd.CreateContextWithDefaultKubeconfig(ctxName, clusterInfo.ClusterContext)
err := tf.ContextCmd.CreateContextWithDefaultKubeconfig(ctxName, clusterInfo.ClusterKubeContext)
Expect(err).To(BeNil(), "context should create without any error")
Expect(context.IsContextExists(tf, ctxName)).To(BeTrue(), "context should be available")
Expect(framework.IsContextExists(tf, ctxName)).To(BeTrue(), "context should be available")
contextNames = append(contextNames, ctxName)
})
// Test case: test 'tanzu config server list' command, should list all contexts created as servers
Expand Down
6 changes: 4 additions & 2 deletions test/e2e/config/config_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

"github.com/vmware-tanzu/tanzu-cli/test/e2e/context"
"github.com/vmware-tanzu/tanzu-cli/test/e2e/framework"
)

Expand All @@ -23,14 +22,17 @@ var (
tf *framework.Framework
clusterInfo *framework.ClusterInfo
contextNames []string
err error
)

// BeforeSuite creates KIND cluster needed to test 'tanzu config server' use cases
// initializes the tf
var _ = BeforeSuite(func() {
tf = framework.NewFramework()
// Create KIND cluster, which is used in test cases to create server's/context's
clusterInfo = context.CreateKindCluster(tf, "config-e2e-"+framework.RandomNumber(4))
clusterInfo, err = framework.CreateKindCluster(tf, "config-e2e-"+framework.RandomNumber(4))
Expect(err).To(BeNil(), "should not get any error for KIND cluster creation")

contextNames = make([]string, 0)
})

Expand Down
29 changes: 20 additions & 9 deletions test/e2e/context/context_k8s_lifecycle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@ const ContextNameConfigPrefix = "context-config-k8s-"
// Test suite tests the context life cycle use cases for the k8s target
var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:Context-lifecycle-k8s]", func() {
Context("Context lifecycle tests for k8s target", func() {
// Test case: delete config files and initialize config
It("should initialize configuration successfully", func() {
// delete config files
err := tf.Config.DeleteCLIConfigurationFiles()
Expect(err).To(BeNil())
// call init
err = tf.Config.ConfigInit()
Expect(err).To(BeNil())
// should create config files
Expect(tf.Config.IsCLIConfigurationFilesExists()).To(BeTrue())
})
// Test case: list and delete context's if any exists already, before running test cases.
It("list and delete contexts if any exists already", func() {
By("list and delete contexts if any exists already before running test cases")
Expand All @@ -28,7 +39,7 @@ var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:Context-lifecycle-k8s]",
for _, ctx := range list {
err := tf.ContextCmd.DeleteContext(ctx.Name)
Expect(err).To(BeNil(), "delete context should delete context without any error")
Expect(IsContextExists(tf, ctx.Name)).To(BeFalse(), fmt.Sprintf(ContextShouldNotExists, ctx.Name))
Expect(framework.IsContextExists(tf, ctx.Name)).To(BeFalse(), fmt.Sprintf(framework.ContextShouldNotExists, ctx.Name))
}
list, err = tf.ContextCmd.ListContext()
Expect(err).To(BeNil(), "list context should not return any error")
Expand All @@ -38,19 +49,19 @@ var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:Context-lifecycle-k8s]",
It("create context with kubeconfig and context", func() {
By("create context with kubeconfig and context")
ctxName := ContextNameConfigPrefix + framework.RandomString(4)
err := tf.ContextCmd.CreateContextWithKubeconfig(ctxName, clusterInfo.KubeConfigPath, clusterInfo.ClusterContext)
err := tf.ContextCmd.CreateContextWithKubeconfig(ctxName, clusterInfo.KubeConfigPath, clusterInfo.ClusterKubeContext)
Expect(err).To(BeNil(), "context should create without any error")
Expect(IsContextExists(tf, ctxName)).To(BeTrue(), fmt.Sprintf(ContextShouldExistsAsCreated, ctxName))
Expect(framework.IsContextExists(tf, ctxName)).To(BeTrue(), fmt.Sprintf(framework.ContextShouldExistsAsCreated, ctxName))
contextNames = append(contextNames, ctxName)
})
// Test case: (negative test) Create context for k8s target with incorrect kubeconfig file path and its context as input
It("create context with incorrect kubeconfig and context", func() {
By("create context with incorrect kubeconfig and context")
ctxName := ContextNameConfigPrefix + framework.RandomString(4)
err := tf.ContextCmd.CreateContextWithKubeconfig(ctxName, framework.RandomString(4), clusterInfo.ClusterContext)
err := tf.ContextCmd.CreateContextWithKubeconfig(ctxName, framework.RandomString(4), clusterInfo.ClusterKubeContext)
Expect(err).ToNot(BeNil())
Expect(strings.Contains(err.Error(), framework.FailedToCreateContext)).To(BeTrue())
Expect(IsContextExists(tf, ctxName)).To(BeFalse(), fmt.Sprintf(ContextShouldNotExists, ctxName))
Expect(framework.IsContextExists(tf, ctxName)).To(BeFalse(), fmt.Sprintf(framework.ContextShouldNotExists, ctxName))
})
// Test case: (negative test) Create context for k8s target with kubeconfig file path and incorrect context as input
It("create context with kubeconfig and incorrect context", func() {
Expand All @@ -59,15 +70,15 @@ var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:Context-lifecycle-k8s]",
err := tf.ContextCmd.CreateContextWithKubeconfig(ctxName, clusterInfo.KubeConfigPath, framework.RandomString(4))
Expect(err).ToNot(BeNil())
Expect(strings.Contains(err.Error(), framework.FailedToCreateContext)).To(BeTrue())
Expect(IsContextExists(tf, ctxName)).To(BeFalse(), fmt.Sprintf(ContextShouldNotExists, ctxName))
Expect(framework.IsContextExists(tf, ctxName)).To(BeFalse(), fmt.Sprintf(framework.ContextShouldNotExists, ctxName))
})
// Test case: Create context for k8s target with "default" kubeconfig and its context only as input value
It("create context with kubeconfig and context", func() {
By("create context with kubeconfig and context")
ctxName := "context-defaultConfig-" + framework.RandomString(4)
err := tf.ContextCmd.CreateContextWithDefaultKubeconfig(ctxName, clusterInfo.ClusterContext)
err := tf.ContextCmd.CreateContextWithDefaultKubeconfig(ctxName, clusterInfo.ClusterKubeContext)
Expect(err).To(BeNil(), "context should create without any error")
Expect(IsContextExists(tf, ctxName)).To(BeTrue(), fmt.Sprintf(ContextShouldExistsAsCreated, ctxName))
Expect(framework.IsContextExists(tf, ctxName)).To(BeTrue(), fmt.Sprintf(framework.ContextShouldExistsAsCreated, ctxName))
contextNames = append(contextNames, ctxName)
active, err := tf.ContextCmd.GetActiveContext(string(types.TargetK8s))
Expect(err).To(BeNil(), "there should be a active context")
Expand Down Expand Up @@ -98,7 +109,7 @@ var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:Context-lifecycle-k8s]",
By("delete all contexts created in previous tests")
for _, ctx := range contextNames {
err := tf.ContextCmd.DeleteContext(ctx)
Expect(IsContextExists(tf, ctx)).To(BeFalse(), fmt.Sprintf(ContextShouldNotExists, ctx))
Expect(framework.IsContextExists(tf, ctx)).To(BeFalse(), fmt.Sprintf(framework.ContextShouldNotExists, ctx))
Expect(err).To(BeNil(), "delete context should delete context without any error")
}
list := GetAvailableContexts(tf, contextNames)
Expand Down
25 changes: 0 additions & 25 deletions test/e2e/context/context_lifecycle_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,6 @@ import (
"github.com/vmware-tanzu/tanzu-cli/test/e2e/framework"
)

// CreateKindCluster create the k8s KIND cluster in the local Docker environment
func CreateKindCluster(tf *framework.Framework, name string) *framework.ClusterInfo {
ci := &framework.ClusterInfo{Name: name}
_, err := tf.KindCluster.CreateCluster(name)
gomega.Expect(err).To(gomega.BeNil(), "the kind cluster creation should be successful without any error")
endpoint, err := tf.KindCluster.GetClusterEndpoint(name)
gomega.Expect(err).To(gomega.BeNil(), "we need cluster endpoint")
ci.EndPoint = endpoint
ci.ClusterContext = tf.KindCluster.GetClusterContext(name)
ci.KubeConfigPath = tf.KindCluster.GetKubeconfigPath()
return ci
}

// GetTMCClusterInfo returns the TMC cluster info by reading environment variables TANZU_CLI_TMC_UNSTABLE_URL and TANZU_API_TOKEN
func GetTMCClusterInfo() *framework.ClusterInfo {
return &framework.ClusterInfo{EndPoint: os.Getenv(framework.TanzuCliTmcUnstableURL), APIKey: os.Getenv(framework.TanzuAPIToken)}
Expand All @@ -44,18 +31,6 @@ func GetAvailableContexts(tf *framework.Framework, contextNames []string) []stri
return available
}

// IsContextExists checks the given context is exists in the config file by listing the existing contexts in the config file
func IsContextExists(tf *framework.Framework, contextName string) bool {
list, err := tf.ContextCmd.ListContext()
gomega.Expect(err).To(gomega.BeNil(), "list context should not return any error")
for _, context := range list {
if context.Name == contextName {
return true
}
}
return false
}

// GetAvailableServers takes list of servers and returns which are available in the 'tanzu config server list' command
func GetAvailableServers(tf *framework.Framework, serverNames []string) []string {
var available []string
Expand Down
7 changes: 3 additions & 4 deletions test/e2e/context/context_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,19 @@ func TestContext(t *testing.T) {
RunSpecs(t, "Context-K8S Suite")
}

const ContextShouldNotExists = "the context %s should not exists"
const ContextShouldExistsAsCreated = "the context %s should exists as its been created"

var (
tf *framework.Framework
clusterInfo *framework.ClusterInfo
contextNames []string
err error
)

// BeforeSuite created KIND cluster
var _ = BeforeSuite(func() {
tf = framework.NewFramework()
// Create KIND cluster, which is used in test cases to create context's
clusterInfo = CreateKindCluster(tf, "context-e2e-"+framework.RandomNumber(4))
clusterInfo, err = framework.CreateKindCluster(tf, "context-e2e-"+framework.RandomNumber(4))
Expect(err).To(BeNil(), "should not get any error for KIND cluster creation")
contextNames = make([]string, 0)
})

Expand Down
23 changes: 17 additions & 6 deletions test/e2e/context/tmc/context_tmc_lifecycle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,24 @@ var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:Context-lifecycle-tmc]",
contextNames = make([]string, 0)
})
Context("Context lifecycle tests for TMC target", func() {
// Test case: delete config files and initialize config
It("should initialize configuration successfully", func() {
// delete config files
err := tf.Config.DeleteCLIConfigurationFiles()
Expect(err).To(BeNil())
// call init
err = tf.Config.ConfigInit()
Expect(err).To(BeNil())
// should create config files
Expect(tf.Config.IsCLIConfigurationFilesExists()).To(BeTrue())
})
// Test case: list and delete context's if any exists
It("delete context command", func() {
list, err := tf.ContextCmd.ListContext()
Expect(err).To(BeNil(), "list context should not return any error")
for _, ctx := range list {
err := tf.ContextCmd.DeleteContext(ctx.Name)
Expect(context.IsContextExists(tf, ctx.Name)).To(BeFalse(), fmt.Sprintf(ContextShouldNotExists, ctx.Name))
Expect(framework.IsContextExists(tf, ctx.Name)).To(BeFalse(), fmt.Sprintf(ContextShouldNotExists, ctx.Name))
Expect(err).To(BeNil(), "delete context should delete context without any error")
}
list, err = tf.ContextCmd.ListContext()
Expand All @@ -55,7 +66,7 @@ var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:Context-lifecycle-tmc]",
ctxName := ContextNamePrefix + framework.RandomString(4)
err := tf.ContextCmd.CreateContextWithEndPointStaging(ctxName, clusterInfo.EndPoint)
Expect(err).To(BeNil(), "context should create without any error")
Expect(context.IsContextExists(tf, ctxName)).To(BeTrue(), fmt.Sprintf(ContextShouldExistsAsCreated, ctxName))
Expect(framework.IsContextExists(tf, ctxName)).To(BeTrue(), fmt.Sprintf(ContextShouldExistsAsCreated, ctxName))
contextNames = append(contextNames, ctxName)
})
// Test case: (negative test) Create context for TMC target with TMC cluster "incorrect" URL as endpoint
Expand All @@ -64,7 +75,7 @@ var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:Context-lifecycle-tmc]",
err := tf.ContextCmd.CreateContextWithEndPointStaging(ctxName, framework.RandomString(4))
Expect(err).ToNot(BeNil())
Expect(strings.Contains(err.Error(), framework.FailedToCreateContext)).To(BeTrue())
Expect(context.IsContextExists(tf, ctxName)).To(BeFalse(), fmt.Sprintf(ContextShouldNotExists, ctxName))
Expect(framework.IsContextExists(tf, ctxName)).To(BeFalse(), fmt.Sprintf(ContextShouldNotExists, ctxName))
})
// Test case: (negative test) Create context for TMC target with TMC cluster URL as endpoint when api token set as incorrect
It("create tmc context with endpoint and with incorrect api token", func() {
Expand All @@ -74,14 +85,14 @@ var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:Context-lifecycle-tmc]",
os.Setenv(framework.TanzuAPIToken, clusterInfo.APIKey)
Expect(err).ToNot(BeNil())
Expect(strings.Contains(err.Error(), framework.FailedToCreateContext)).To(BeTrue())
Expect(context.IsContextExists(tf, ctxName)).To(BeFalse(), fmt.Sprintf(ContextShouldNotExists, ctxName))
Expect(framework.IsContextExists(tf, ctxName)).To(BeFalse(), fmt.Sprintf(ContextShouldNotExists, ctxName))
})
// Test case: Create context for TMC target with TMC cluster URL as endpoint, and validate the active context, should be recently create context
It("create tmc context with endpoint and check active context", func() {
ctxName := ContextNamePrefix + framework.RandomString(4)
err := tf.ContextCmd.CreateContextWithEndPointStaging(ctxName, clusterInfo.EndPoint)
Expect(err).To(BeNil(), "context should create without any error")
Expect(context.IsContextExists(tf, ctxName)).To(BeTrue(), fmt.Sprintf(ContextShouldExistsAsCreated, ctxName))
Expect(framework.IsContextExists(tf, ctxName)).To(BeTrue(), fmt.Sprintf(ContextShouldExistsAsCreated, ctxName))
contextNames = append(contextNames, ctxName)
active, err := tf.ContextCmd.GetActiveContext(string(types.TargetTMC))
Expect(err).To(BeNil(), "there should be a active context")
Expand Down Expand Up @@ -109,7 +120,7 @@ var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:Context-lifecycle-tmc]",
It("delete context command", func() {
for _, ctx := range contextNames {
err := tf.ContextCmd.DeleteContext(ctx)
Expect(context.IsContextExists(tf, ctx)).To(BeFalse(), fmt.Sprintf(ContextShouldNotExists+" as been deleted", ctx))
Expect(framework.IsContextExists(tf, ctx)).To(BeFalse(), fmt.Sprintf(ContextShouldNotExists+" as been deleted", ctx))
Expect(err).To(BeNil(), "delete context should delete context without any error")
}
list := context.GetAvailableContexts(tf, contextNames)
Expand Down
12 changes: 7 additions & 5 deletions test/e2e/framework/cluster_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ type ClusterOps interface {
GetClusterContext(clusterName string) string
// GetKubeconfigPath returns the default kubeconfig path
GetKubeconfigPath() string
// ApplyConfig applies the given configFilePath on to the given contextName cluster context
ApplyConfig(contextName, configFilePath string) error
}

// ClusterInfo holds the general cluster details
type ClusterInfo struct {
Name string
ClusterContext string
EndPoint string
KubeConfigPath string
APIKey string
Name string
ClusterKubeContext string
EndPoint string
KubeConfigPath string
APIKey string
}
13 changes: 13 additions & 0 deletions test/e2e/framework/cluster_kind.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (

"github.com/pkg/errors"

"github.com/vmware-tanzu/tanzu-plugin-runtime/log"

"gopkg.in/yaml.v3"
configapi "k8s.io/client-go/tools/clientcmd/api/v1"
)
Expand Down Expand Up @@ -76,6 +78,17 @@ func (kc *kindCluster) ClusterStatus(kindClusterName string) (output string, err
return stdOutBuffer.String(), err
}

func (kc *kindCluster) ApplyConfig(contextName, configFilePath string) error {
applyCmd := fmt.Sprintf(KubectlApply, contextName, configFilePath)
stdOut, stdErr, err := kc.CmdOps.Exec(applyCmd)
if err != nil {
log.Errorf(ErrorLogForCommandWithErrStdErrAndStdOut, applyCmd, err.Error(), stdErr.String(), stdOut.String())
return err
}
log.Infof("the config:%s applied successfully to context:%s", configFilePath, contextName)
return err
}

// GetClusterEndpoint returns given kind cluster control plane endpoint
func (kc *kindCluster) GetClusterEndpoint(kindClusterName string) (endpoint string, err error) {
stdOut, err := kc.ContainerRuntimeStatus()
Expand Down
Loading

0 comments on commit 70755fd

Please sign in to comment.