Skip to content

Commit

Permalink
E2E - config server tooling and test cases implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Chandra Pamuluri committed Mar 8, 2023
1 parent 4c2443d commit 34e949d
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 31 deletions.
74 changes: 74 additions & 0 deletions test/e2e/config/config_server_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2023 VMware, Inc. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

// Package config_e2e_test provides config command specific E2E test cases
package config_e2e_test

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"
)

const ContextNameConfigPrefix = "config-k8s-"

// This test suite tests the 'tanzu config server' use cases
// As part of this suite, create a KIND cluster, and creates context's
// tests the 'tanzu config server list' and 'tanzu config server delete' commands
var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:Config-Server]", func() {
var (
tf *framework.Framework
clusterInfo *framework.ClusterInfo
contextNames []string
)

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))
contextNames = make([]string, 0)
})
Context("tanzu config server command test cases ", func() {
// Test case: Create context for k8s target with kubeconfig and its context as input
It("create context with kubeconfig and context", func() {
ctxName := ContextNameConfigPrefix + framework.RandomString(4)
err := tf.ContextCmd.CreateConextWithKubeconfig(ctxName, clusterInfo.KubeConfigPath, clusterInfo.ClusterContext)
Expect(err).To(BeNil(), "context should create without any error")
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 kubeconfig and context", func() {
ctxName := "context-defaultConfig-" + framework.RandomString(4)
err := tf.ContextCmd.CreateContextWithDefaultKubeconfig(ctxName, clusterInfo.ClusterContext)
Expect(err).To(BeNil(), "context should create without any error")
contextNames = append(contextNames, ctxName)
})
// Test case: test 'tanzu config server list' command, should list all contexts created as servers
It("list servers should have all added contexts", func() {
list, err := tf.Config.ConfigServerList()
Expect(err).To(BeNil(), "config server list command should list available servers")
Expect(len(list)).To(Equal(len(contextNames)), "list context should have all contexts (as servers) added in previous tests")
})
// Test case: test 'tanzu config server delete' command, make sure to delete all context's created in previous test cases
It("delete server command", func() {
for _, ctx := range contextNames {
err := tf.Config.ConfigServerDelete(ctx)
Expect(err).To(BeNil(), "delete server should delete server without any error")
}
list := context.GetAvailableServers(tf, contextNames)
Expect(len(list)).To(Equal(0), "delete server should have deleted all given server names")
})
// Test case: (negative test) test 'tanzu context delete' command for context name which is not exists
It("delete server which is not exists", func() {
err := tf.Config.ConfigServerDelete(framework.RandomString(4))
Expect(err).ToNot(BeNil())
})
})
AfterSuite(func() {
// delete the KIND cluster which was created in the suite setup
_, err := tf.KindCluster.DeleteCluster(clusterInfo.Name)
Expect(err).To(BeNil(), "kind cluster should be deleted without any error")
})
})
3 changes: 2 additions & 1 deletion test/e2e/config/config_suite_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Copyright 2023 VMware, Inc. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package confige2e
// Package config_e2e_test provides config command specific E2E test cases
package config_e2e_test

import (
"testing"
Expand Down
39 changes: 22 additions & 17 deletions test/e2e/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

// Package config_e2e_test provides config command specific E2E test cases
package confige2e
package config_e2e_test

import (
. "github.com/onsi/ginkgo"
Expand All @@ -13,18 +13,24 @@ import (

const TRUE = "true"

var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:Command-Config]", func() {
// This test suite tests `tanzu config` life cycle tests
// tests `tanzu config init` by deleting the existing config files
// tests `tanzu config init` and make sure previous set flags are not deleted
// tests `tanzu config set` and `tanzu config unset` commands
var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:config]", func() {
var (
tf *framework.Framework
tf *framework.Framework
randomFeatureFlag string
)
BeforeEach(func() {
tf = framework.NewFramework()
randomFeatureFlag = "features.global." + "e2e-test-" + framework.RandomString(4)
})
Context("config feature flag operations", func() {
When("new config flag set with value", func() {
It("should set flag and unset flag successfully", func() {
randomFlagName := "e2e-test-" + framework.RandomString(4)
randomFeatureFlagPath := "features.global." + randomFlagName
flagName := "e2e-test-" + framework.RandomString(4)
randomFeatureFlagPath := "features.global." + flagName
flagVal := TRUE
err := tf.Config.ConfigSetFeatureFlag(randomFeatureFlagPath, flagVal)
Expect(err).To(BeNil())
Expand All @@ -41,7 +47,7 @@ var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:Command-Config]", func()
Expect(val).Should(Equal(""))
})
})
When("config init called when config files not exists", func() {
When("config init called when config files not exists and test re-init use case", func() {
It("should initialize configuration successfully", func() {
// delete config files
err := tf.Config.DeleteCLIConfigurationFiles()
Expand All @@ -51,28 +57,27 @@ var _ = framework.CLICoreDescribe("[Tests:E2E][Feature:Command-Config]", func()
Expect(err).To(BeNil())
// should create config files
Expect(tf.Config.IsCLIConfigurationFilesExists()).To(BeTrue())

})
It("should able to set new feature flag", func() {
// set feature flag
randomFlagName := "e2e-test-" + framework.RandomString(4)
randomFeatureFlagPath := "features.global." + randomFlagName
flagVal := TRUE
err = tf.Config.ConfigSetFeatureFlag(randomFeatureFlagPath, flagVal)
err := tf.Config.ConfigSetFeatureFlag(randomFeatureFlag, TRUE)
Expect(err).To(BeNil())

val, err := tf.Config.ConfigGetFeatureFlag(randomFeatureFlagPath)
val, err := tf.Config.ConfigGetFeatureFlag(randomFeatureFlag)
Expect(err).To(BeNil())
Expect(val).Should(Equal(TRUE))

})
It("re-init and should not remove previous set flags", func() {
// call init
err = tf.Config.ConfigInit()
err := tf.Config.ConfigInit()
Expect(err).To(BeNil())
// second run of init should not remove the existing feature flag
val, err = tf.Config.ConfigGetFeatureFlag(randomFeatureFlagPath)
val, err := tf.Config.ConfigGetFeatureFlag(randomFeatureFlag)
Expect(err).To(BeNil())
Expect(val).Should(Equal("true"))
Expect(val).Should(Equal(TRUE))

// unset the feature flag
err = tf.Config.ConfigUnsetFeature(randomFeatureFlagPath)
err = tf.Config.ConfigUnsetFeature(randomFeatureFlag)
Expect(err).To(BeNil())
})
})
Expand Down
14 changes: 14 additions & 0 deletions test/e2e/context/context_lifecycle_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,17 @@ func GetAvailableContexts(tf *framework.Framework, contextNames []string) []stri
}
return available
}

// 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
list, err := tf.Config.ConfigServerList()
gomega.Expect(err).To(gomega.BeNil(), "server list should not return any error")
set := framework.SliceToSet(serverNames)
for _, server := range list {
if _, ok := set[server.Name]; ok {
available = append(available, server.Name)
}
}
return available
}
30 changes: 24 additions & 6 deletions test/e2e/framework/config_lifecycle_operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
package framework

import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/pkg/errors"
"gopkg.in/yaml.v3"

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

configapi "github.com/vmware-tanzu/tanzu-plugin-runtime/config/types"
)

Expand All @@ -33,7 +37,7 @@ type ConfigLifecycleOps interface {
// GetConfig gets the tanzu config
GetConfig() (*configapi.ClientConfig, error)
// ConfigServerList returns the server list
ConfigServerList() error
ConfigServerList() ([]Server, error)
// ConfigServerDelete deletes given server from tanzu config
ConfigServerDelete(serverName string) error
// DeleteCLIConfigurationFiles deletes cli configuration files
Expand Down Expand Up @@ -102,15 +106,29 @@ func (co *configOps) ConfigInit() (err error) {
}

// ConfigServerList returns the server list
// TODO: should return the servers info in proper format
func (co *configOps) ConfigServerList() (err error) {
_, _, err = co.Exec(ConfigServerList)
return
func (co *configOps) ConfigServerList() ([]Server, error) {
stdOut, _, err := co.Exec(ConfigServerList)
if err != nil {
log.Errorf("error while executing `config server list`, error:%s", err.Error())
return nil, err
}
jsonStr := stdOut.String()
var list []Server
err = json.Unmarshal([]byte(jsonStr), &list)
if err != nil {
log.Errorf("failed to construct node from config server list output:'%s' error:'%s' ", jsonStr, err.Error())
return nil, errors.Wrapf(err, "failed to construct node from config server list output:'%s'", jsonStr)
}
return list, nil
}

// ConfigServerDelete deletes a server from tanzu config
func (co *configOps) ConfigServerDelete(serverName string) error {
_, _, err := co.Exec(ConfigServerDelete + serverName)
configDelCmd := fmt.Sprintf(ConfigServerDelete, serverName)
_, _, err := co.Exec(configDelCmd)
if err != nil {
log.Error(err, "error while running: "+configDelCmd)
}
return err
}

Expand Down
10 changes: 6 additions & 4 deletions test/e2e/framework/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const (
ConfigUnset = "tanzu config unset "
ConfigInit = "tanzu config init"
ConfigServerList = "tanzu config server list"
ConfigServerDelete = "tanzu config server delete "
ConfigServerDelete = "tanzu config server delete %s"

// Plugin commands
AddPluginSource = "tanzu plugin source add --name %s --type %s --uri %s"
Expand Down Expand Up @@ -74,9 +74,11 @@ const (
TargetTypeK8s = "kubernetes"
)

var TestDirPath string
var TestPluginsDirPath string
var TestStandalonePluginsPath string
var (
TestDirPath string
TestPluginsDirPath string
TestStandalonePluginsPath string
)

// CLICoreDescribe annotates the test with the CLICore label.
func CLICoreDescribe(text string, body func()) bool {
Expand Down
9 changes: 6 additions & 3 deletions test/e2e/framework/output_handling.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ type ContextInfo struct {
} `json:"clusterOpts"`
}

type PluginCompatibilityConf struct {
PluginNames []string `json:"plugins"`
TestCentralRepoURL string `json:"test-central-repo-url"`
type Server struct {
Context string `json:"context"`
Endpoint string `json:"endpoint"`
Name string `json:"name"`
Path string `json:"path"`
Type string `json:"type"`
}

0 comments on commit 34e949d

Please sign in to comment.