Skip to content

Commit

Permalink
Make kubernetes and application-engine type current contexts mutual e…
Browse files Browse the repository at this point in the history
…xclusive

- Make kubernetes and application-engine current contexts mutual exclusive, which means if the k8s context is set as current(active) the TAE context would be removed and vice-versa.

Signed-off-by: Prem Kumar Kalle <[email protected]>
  • Loading branch information
prkalle committed Oct 10, 2023
1 parent 0b93726 commit 6807eb0
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 76 deletions.
37 changes: 37 additions & 0 deletions config/contexts.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,14 @@ func setCurrentContext(node *yaml.Node, ctx *configtypes.Context) (persist bool,
currentContextNode.Content = append(currentContextNode.Content, nodeutils.CreateScalarNode(string(ctx.Target), ctx.Name)...)
persist = true
}
// maintain mutual exclusive behavior among all the current context types except TMC
// (i.e. there can only be one active current context among all the context types except TMC.
// TMC context type can still be active when other context types are active)
if persist {
if err := updateMutualExclusiveCurrentContexts(node, ctx); err != nil {
return persist, err
}
}
return persist, err
}

Expand Down Expand Up @@ -443,3 +451,32 @@ func removeContext(node *yaml.Node, name string) error {
contextsNode.Content = contexts
return nil
}

// updateMutualExclusiveCurrentContexts updates the current contexts to maintain
// mutual exclusive behavior among the current context types except TMC
func updateMutualExclusiveCurrentContexts(node *yaml.Node, ctx *configtypes.Context) error {
if ctx.Target == configtypes.TargetTMC {
return nil
}

cfg, err := convertNodeToClientConfig(node)
if err != nil {
return err
}
// deactivate all the other existing current contexts that are not TMC
for target, contextName := range cfg.CurrentContext {
if target == ctx.Target || target == configtypes.TargetTMC {
continue
}

err = removeCurrentContext(node, &configtypes.Context{Target: target})
if err != nil {
return err
}
err = removeCurrentServer(node, contextName)
if err != nil {
return err
}
}
return nil
}
230 changes: 154 additions & 76 deletions config/contexts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,21 @@ package config
import (
"testing"

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

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"

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

func TestCliCmdSuite(t *testing.T) {
gomega.RegisterFailHandler(Fail)
RunSpecs(t, "config suite")
}

func TestSetGetDeleteContext(t *testing.T) {
// Setup config data
_, cleanUp := setupTestConfig(t, &CfgTestData{})
Expand Down Expand Up @@ -430,7 +438,7 @@ func TestSetContextWithDiscoverySource(t *testing.T) {
}
}

func setupForGetContext(t *testing.T) {
func setupForGetContext() error {
// setup
cfg := &configtypes.ClientConfig{
KnownContexts: []*configtypes.Context{
Expand Down Expand Up @@ -477,18 +485,18 @@ func setupForGetContext(t *testing.T) {
CurrentContext: map[configtypes.Target]string{
configtypes.TargetK8s: "test-mc-2",
configtypes.TargetTMC: "test-tmc",
configtypes.TargetTAE: "test-tae",
},
}
func() {
return func() error {
LocalDirName = TestLocalDirName
err := StoreClientConfig(cfg)
assert.NoError(t, err)
return err
}()
}

func TestGetContext(t *testing.T) {
setupForGetContext(t)
err := setupForGetContext()
assert.NoError(t, err)

defer func() {
cleanupDir(LocalDirName)
Expand Down Expand Up @@ -532,7 +540,8 @@ func TestGetContext(t *testing.T) {
}

func TestContextExists(t *testing.T) {
setupForGetContext(t)
err := setupForGetContext()
assert.NoError(t, err)

defer func() {
cleanupDir(LocalDirName)
Expand Down Expand Up @@ -740,7 +749,8 @@ func TestSetContext(t *testing.T) {

func TestRemoveContext(t *testing.T) {
// setup
setupForGetContext(t)
err := setupForGetContext()
assert.NoError(t, err)
defer func() {
cleanupDir(LocalDirName)
}()
Expand Down Expand Up @@ -795,97 +805,66 @@ func TestRemoveContext(t *testing.T) {
}
}

func TestSetCurrentContext(t *testing.T) {
func TestGetAllCurrentContexts(t *testing.T) {
// setup
setupForGetContext(t)
err := setupForGetContext()
assert.NoError(t, err)
defer func() {
cleanupDir(LocalDirName)
}()
tcs := []struct {
name string
target configtypes.Target
ctxName string
currServer string
errStr string
}{
{
name: "success tmc",
ctxName: "test-tmc",
target: configtypes.TargetTMC,
},
{
name: "success k8s",
ctxName: "test-mc",
target: configtypes.TargetK8s,
currServer: "test-mc",
},
{
name: "success tae",
ctxName: "test-tae",
target: configtypes.TargetTAE,
},
{
name: "success tmc after setting k8s",
ctxName: "test-tmc",
target: configtypes.TargetTMC,
},
{
name: "failure",
ctxName: "test",
errStr: "context test not found",
},
}

for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {
prevSrv, _ := GetCurrentServer()
currentContextMap, err := GetAllCurrentContextsMap()
assert.NoError(t, err)
assert.Equal(t, "test-mc-2", currentContextMap[configtypes.TargetK8s].Name)
assert.Equal(t, "test-tmc", currentContextMap[configtypes.TargetTMC].Name)
assert.Nil(t, currentContextMap[configtypes.TargetTAE])

err := SetCurrentContext(tc.ctxName)
if tc.errStr == "" {
assert.NoError(t, err)
} else {
assert.EqualError(t, err, tc.errStr)
}
currCtx, err := GetCurrentContext(tc.target)
if tc.errStr == "" {
assert.NoError(t, err)
assert.Equal(t, tc.ctxName, currCtx.Name)
} else {
assert.Error(t, err)
}
currSrv, err := GetCurrentServer()
assert.NoError(t, err)
if tc.errStr == "" {
if tc.currServer == "" {
assert.Equal(t, prevSrv.Name, currSrv.Name)
} else {
assert.Equal(t, tc.currServer, currSrv.Name)
}
}
})
}
currentContextsList, err := GetAllCurrentContextsList()
assert.NoError(t, err)
assert.Contains(t, currentContextsList, "test-mc-2")
assert.Contains(t, currentContextsList, "test-tmc")
assert.NotContains(t, currentContextsList, "test-tae")

currentContextMap, err := GetAllCurrentContextsMap()
// set the tae context (k8s and tae current contexts are mutual exclusive)
err = SetCurrentContext("test-tae")
assert.NoError(t, err)
currentContextMap, err = GetAllCurrentContextsMap()
assert.NoError(t, err)
assert.Equal(t, "test-mc", currentContextMap[configtypes.TargetK8s].Name)
assert.Nil(t, currentContextMap[configtypes.TargetK8s])
assert.Equal(t, "test-tmc", currentContextMap[configtypes.TargetTMC].Name)
assert.Equal(t, "test-tae", currentContextMap[configtypes.TargetTAE].Name)

currentContextsList, err := GetAllCurrentContextsList()
currentContextsList, err = GetAllCurrentContextsList()
assert.NoError(t, err)
assert.Contains(t, currentContextsList, "test-mc")
assert.NotContains(t, currentContextsList, "test-mc2")
assert.Contains(t, currentContextsList, "test-tmc")
assert.Contains(t, currentContextsList, "test-tae")

// remove the tae current context
err = RemoveCurrentContext(configtypes.TargetTAE)
assert.NoError(t, err)
currentContextMap, err = GetAllCurrentContextsMap()
assert.NoError(t, err)
assert.Nil(t, currentContextMap[configtypes.TargetK8s])
assert.Equal(t, "test-tmc", currentContextMap[configtypes.TargetTMC].Name)
assert.Nil(t, currentContextMap[configtypes.TargetTAE])

currentContextsList, err = GetAllCurrentContextsList()
assert.NoError(t, err)
assert.NotContains(t, currentContextsList, "test-mc")
assert.Contains(t, currentContextsList, "test-tmc")
assert.NotContains(t, currentContextsList, "test-tae")
}

func TestRemoveCurrentContext(t *testing.T) {
// setup
setupForGetContext(t)
err := setupForGetContext()
assert.NoError(t, err)
defer func() {
cleanupDir(LocalDirName)
}()

err := RemoveCurrentContext(configtypes.TargetK8s)
err = RemoveCurrentContext(configtypes.TargetK8s)
assert.NoError(t, err)

currCtx, err := GetCurrentContext(configtypes.TargetK8s)
Expand Down Expand Up @@ -1284,3 +1263,102 @@ func TestSetContextWithEmptyName(t *testing.T) {
})
}
}

var _ = Describe("testing SetCurrentContext", func() {
var (
err error
)

BeforeEach(func() {
// setup
err := setupForGetContext()
gomega.Expect(err).To(gomega.BeNil())
})
AfterEach(func() {
cleanupDir(LocalDirName)
})

Context("tmc context as current context", func() {
It("should set tmc context as current context successfully", func() {
err = SetCurrentContext("test-tmc")
gomega.Expect(err).To(gomega.BeNil())
validateCurrentContext(configtypes.TargetTMC, "test-tmc", true, "test-mc-2")
})
})
Context("k8s context as current context", func() {
It("should set k8s context as current context successfully", func() {
err = SetCurrentContext("test-mc")
gomega.Expect(err).To(gomega.BeNil())
validateCurrentContext(configtypes.TargetK8s, "test-mc", true, "test-mc")

})
})
Context("tae context as current context", func() {
It("should set tae context as current context successfully", func() {
//Remove the k8s current context set during initial setup
err = RemoveCurrentContext(configtypes.TargetK8s)
gomega.Expect(err).To(gomega.BeNil())

err = SetCurrentContext("test-tae")
gomega.Expect(err).To(gomega.BeNil())
validateCurrentContext(configtypes.TargetTAE, "test-tae", false, "")

})
})
Context("k8s context as current context after tmc context ", func() {
It("should have k8s and tmc contexts as current for their respective targets", func() {
err = SetCurrentContext("test-tmc")
gomega.Expect(err).To(gomega.BeNil())
validateCurrentContext(configtypes.TargetTMC, "test-tmc", true, "test-mc-2")

err = SetCurrentContext("test-mc")
gomega.Expect(err).To(gomega.BeNil())
validateCurrentContext(configtypes.TargetK8s, "test-mc", true, "test-mc")

})
})
Context("k8s context as current context after tae context(mutual-exclusion test between k8s and tae) ", func() {
It("should have only k8s as current context and tae context should be removed from the current context", func() {
err = SetCurrentContext("test-tae")
gomega.Expect(err).To(gomega.BeNil())
validateCurrentContext(configtypes.TargetTAE, "test-tae", false, "")

err = SetCurrentContext("test-mc")
gomega.Expect(err).To(gomega.BeNil())
validateCurrentContext(configtypes.TargetK8s, "test-mc", true, "test-mc")

_, err = GetCurrentContext(configtypes.TargetTAE)
gomega.Expect(err).ToNot(gomega.BeNil())
gomega.Expect(err.Error()).To(gomega.ContainSubstring(`no current context set for target "application-engine"`))
})
})
Context("tae context as current context after k8s context(mutual-exclusion test between k8s and tae) ", func() {
It("should have only tae as current context and k8s context should be removed from the current context", func() {
err = SetCurrentContext("test-mc")
gomega.Expect(err).To(gomega.BeNil())
validateCurrentContext(configtypes.TargetK8s, "test-mc", true, "test-mc")

err = SetCurrentContext("test-tae")
gomega.Expect(err).To(gomega.BeNil())
validateCurrentContext(configtypes.TargetTAE, "test-tae", false, "")

_, err = GetCurrentContext(configtypes.TargetK8s)
gomega.Expect(err).ToNot(gomega.BeNil())
gomega.Expect(err.Error()).To(gomega.ContainSubstring(`no current context set for target "kubernetes"`))
})
})
})

func validateCurrentContext(target configtypes.Target, ctxName string, isServerExpected bool, serverName string) {
c, err := GetCurrentContext(target)
gomega.Expect(err).To(gomega.BeNil())
gomega.Expect(c.Name).To(gomega.Equal(ctxName))

server, err := GetCurrentServer()
if !isServerExpected {
gomega.Expect(err).ToNot(gomega.BeNil())
} else {
gomega.Expect(err).To(gomega.BeNil())
gomega.Expect(server.Name).To(gomega.Equal(serverName))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b h1:FQ7+9fxhyp82ks9vAuyPzG0/vVbWwMwLJ+P6yJI5FN8=
github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b/go.mod h1:HMcgvsgd0Fjj4XXDkbjdmlbI505rUPBs6WBMYg2pXks=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU=
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand All @@ -27,7 +32,11 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tj/assert v0.0.3 h1:Df/BlaZ20mq6kuai7f5z2TvPFiwC3xaWJSDQNiIS3Rk=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down

0 comments on commit 6807eb0

Please sign in to comment.