Skip to content

Commit

Permalink
Refactor the deprecated APIs (vmware-tanzu#616)
Browse files Browse the repository at this point in the history
* Update deprecated apis like feature flag apis

* Remove unused builder publish command

* Address review comments

* Implement sync of active contexts and server
  • Loading branch information
mpanchajanya authored Jan 21, 2024
1 parent beb7fde commit 3e6a2fb
Show file tree
Hide file tree
Showing 10 changed files with 968 additions and 405 deletions.
898 changes: 898 additions & 0 deletions go.work.sum

Large diffs are not rendered by default.

101 changes: 19 additions & 82 deletions pkg/command/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@ import (
"gopkg.in/yaml.v3"

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

"github.com/vmware-tanzu/tanzu-cli/pkg/cli"
"github.com/vmware-tanzu/tanzu-cli/pkg/config"
"github.com/vmware-tanzu/tanzu-cli/pkg/pluginsupplier"
"github.com/vmware-tanzu/tanzu-plugin-runtime/log"
)
Expand Down Expand Up @@ -123,26 +121,17 @@ var setConfigCmd = &cobra.Command{
return errors.Errorf("only PATH and <value> are allowed")
}

// Acquire tanzu config lock
configlib.AcquireTanzuConfigLock()
defer configlib.ReleaseTanzuConfigLock()

cfg, err := configlib.GetClientConfigNoLock()
if err != nil {
return err
}

err = setConfiguration(cfg, args[0], args[1])
err := setConfiguration(args[0], args[1])
if err != nil {
return err
}

return configlib.StoreClientConfig(cfg)
return nil
},
}

// setConfiguration sets the key-value pair for the given path
func setConfiguration(cfg *configtypes.ClientConfig, pathParam, value string) error {
func setConfiguration(pathParam, value string) error {
// parse the param
paramArray := strings.Split(pathParam, ".")
if len(paramArray) < 2 {
Expand All @@ -153,74 +142,26 @@ func setConfiguration(cfg *configtypes.ClientConfig, pathParam, value string) er

switch configLiteral {
case ConfigLiteralFeatures:
return setFeatures(cfg, paramArray, value)
if len(paramArray) != 3 {
return errors.New("unable to parse config path parameter into three parts [" + strings.Join(paramArray, ".") + "] (was expecting 'features.<plugin>.<feature>'")
}
return configlib.SetFeature(paramArray[1], paramArray[2], value)
case ConfigLiteralEnv:
return setEnvs(cfg, paramArray, value)
if len(paramArray) != 2 {
return errors.New("unable to parse config path parameter into two parts [" + strings.Join(paramArray, ".") + "] (was expecting 'env.<variable>'")
}
return configlib.SetEnv(paramArray[1], value)
default:
return errors.New("unsupported config path parameter [" + configLiteral + "] (was expecting 'features.<plugin>.<feature>' or 'env.<env_variable>')")
}
}

func setFeatures(cfg *configtypes.ClientConfig, paramArray []string, value string) error {
if len(paramArray) != 3 {
return errors.New("unable to parse config path parameter into three parts [" + strings.Join(paramArray, ".") + "] (was expecting 'features.<plugin>.<feature>'")
}
pluginName := paramArray[1]
featureName := paramArray[2]

if cfg.ClientOptions == nil {
cfg.ClientOptions = &configtypes.ClientOptions{}
}
if cfg.ClientOptions.Features == nil {
cfg.ClientOptions.Features = make(map[string]configtypes.FeatureMap)
}
if cfg.ClientOptions.Features[pluginName] == nil {
cfg.ClientOptions.Features[pluginName] = configtypes.FeatureMap{}
}
cfg.ClientOptions.Features[pluginName][featureName] = value
return nil
}

func setEnvs(cfg *configtypes.ClientConfig, paramArray []string, value string) error {
if len(paramArray) != 2 {
return errors.New("unable to parse config path parameter into two parts [" + strings.Join(paramArray, ".") + "] (was expecting 'env.<variable>'")
}
envVariable := paramArray[1]

if cfg.ClientOptions == nil {
cfg.ClientOptions = &configtypes.ClientOptions{}
}
if cfg.ClientOptions.Env == nil {
cfg.ClientOptions.Env = make(map[string]string)
}

cfg.ClientOptions.Env[envVariable] = value
return nil
}

var initConfigCmd = &cobra.Command{
Use: "init",
Short: "Initialize config with defaults",
Long: "Initialize config with defaults including plugin specific defaults such as default feature flags for all active and installed plugins",
ValidArgsFunction: noMoreCompletions,
RunE: func(cmd *cobra.Command, args []string) error {
// Acquire tanzu config lock
configlib.AcquireTanzuConfigLock()
defer configlib.ReleaseTanzuConfigLock()

cfg, err := configlib.GetClientConfigNoLock()
if err != nil {
return err
}
if cfg.ClientOptions == nil {
cfg.ClientOptions = &configtypes.ClientOptions{}
}
//nolint: staticcheck
//SA1019: cfg.ClientOptions.CLI is deprecated: CLI has been deprecated and will be removed from future version. use CoreCliOptions (staticcheck)
if cfg.ClientOptions.CLI == nil {
cfg.ClientOptions.CLI = &configtypes.CLIOptions{}
}

plugins, err := pluginsupplier.GetInstalledPlugins()
if err != nil {
return err
Expand All @@ -230,12 +171,10 @@ var initConfigCmd = &cobra.Command{
// Plugins that are installed but are not active plugin will not be processed here
// and defaultFeatureFlags will not be configured for those plugins
for _, desc := range plugins {
config.AddDefaultFeatureFlagsIfMissing(cfg, desc.DefaultFeatureFlags)
}

err = configlib.StoreClientConfig(cfg)
if err != nil {
return err
err := configlib.ConfigureFeatureFlags(desc.DefaultFeatureFlags, configlib.SkipIfExists())
if err != nil {
return err
}
}

log.Success("successfully initialized the config")
Expand Down Expand Up @@ -340,16 +279,14 @@ func completionGetEnvAndFeatures() []string {
}

// Retrieve client config node
cfg, err := configlib.GetClientConfig()
featureFlags, err := configlib.GetAllFeatureFlags()
if err != nil {
return comps
}

if cfg.ClientOptions != nil && cfg.ClientOptions.Features != nil {
for plugin, features := range cfg.ClientOptions.Features {
for name, value := range features {
comps = append(comps, fmt.Sprintf("%s.%s.%s\tValue: %q", ConfigLiteralFeatures, plugin, name, value))
}
for pluginKey, features := range featureFlags {
for name, value := range features {
comps = append(comps, fmt.Sprintf("%s.%s.%s\tValue: %q", ConfigLiteralFeatures, pluginKey, name, value))
}
}

Expand Down
48 changes: 6 additions & 42 deletions pkg/command/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ import (
"github.com/stretchr/testify/assert"

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

// Test_config_MalformedPathArg validates functionality when an invalid argument is provided.
func TestConfigMalformedPathArg(t *testing.T) {
err := setConfiguration(nil, "invalid-arg", "")
err := setConfiguration("invalid-arg", "")
if err == nil {
t.Error("Malformed path argument should have resulted in an error")
}
Expand All @@ -29,7 +28,7 @@ func TestConfigMalformedPathArg(t *testing.T) {

// Test_config_InvalidPathArg validates functionality when an invalid argument is provided.
func TestConfigInvalidPathArg(t *testing.T) {
err := setConfiguration(nil, "shouldbefeatures.plugin.feature", "")
err := setConfiguration("shouldbefeatures.plugin.feature", "")
if err == nil {
t.Error("Invalid path argument should have resulted in an error")
}
Expand All @@ -39,70 +38,35 @@ func TestConfigInvalidPathArg(t *testing.T) {
}
}

// TestConfigGlobalFeature validates functionality when global feature path argument is provided.
func TestConfigGlobalFeature(t *testing.T) {
cfg := &configtypes.ClientConfig{}
value := "bar"
err := setConfiguration(cfg, "features.global.foo", value)
if err != nil {
t.Errorf("Unexpected error returned for global features path argument: %s", err.Error())
}

if cfg.ClientOptions.Features["global"]["foo"] != value {
t.Error("cfg.ClientOptions.Features[\"global\"][\"foo\"] was not assigned the value \"" + value + "\"")
}
}

// TestConfigFeature validates functionality when normal feature path argument is provided.
func TestConfigFeature(t *testing.T) {
cfg := &configtypes.ClientConfig{}
value := "barr"
err := setConfiguration(cfg, "features.any-plugin.foo", value)
if err != nil {
t.Errorf("Unexpected error returned for any-plugin features path argument: %s", err.Error())
}

if cfg.ClientOptions.Features["any-plugin"]["foo"] != value {
t.Error("cfg.ClientOptions.Features[\"any-plugin\"][\"foo\"] was not assigned the value \"" + value + "\"")
}
}

// TestConfigSetUnsetEnv validates set and unset functionality when env config path argument is provided.
func TestConfigSetUnsetEnv(t *testing.T) {
cfg := &configtypes.ClientConfig{}
value := "baar"
err := setConfiguration(cfg, "env.foo", value)
err := setConfiguration("env.foo", value)
assert.Nil(t, err)
assert.Equal(t, value, cfg.ClientOptions.Env["foo"])

err = unsetConfiguration("env.foo")
assert.Nil(t, err)

cfg, err = configlib.GetClientConfigNoLock()
cfg, err := configlib.GetClientConfigNoLock()
assert.NoError(t, err)
assert.Equal(t, cfg.ClientOptions.Env["foo"], "")
}

// TestConfigIncorrectConfigLiteral validates incorrect config literal
func TestConfigIncorrectConfigLiteral(t *testing.T) {
cfg := &configtypes.ClientConfig{}
value := "b"
err := setConfiguration(cfg, "fake.any-plugin.foo", value)
err := setConfiguration("fake.any-plugin.foo", value)
assert.NotNil(t, err)
assert.Contains(t, err.Error(), "unsupported config path parameter [fake] (was expecting 'features.<plugin>.<feature>' or 'env.<env_variable>')")
}

// TestConfigEnv validates functionality when normal env path argument is provided.
func TestConfigEnv(t *testing.T) {
cfg := &configtypes.ClientConfig{}
value := "baarr"
err := setConfiguration(cfg, "env.any-plugin", value)
err := setConfiguration("env.any-plugin", value)
if err != nil {
t.Errorf("Unexpected error returned for any-plugin env path argument: %s", err.Error())
}
if cfg.ClientOptions.Env["any-plugin"] != value {
t.Error("cfg.ClientOptions.Features[\"any-plugin\"][\"foo\"] was not assigned the value \"" + value + "\"")
}
}

func TestCompletionConfig(t *testing.T) {
Expand Down
9 changes: 1 addition & 8 deletions pkg/command/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (

"github.com/vmware-tanzu/tanzu-cli/pkg/catalog"
"github.com/vmware-tanzu/tanzu-cli/pkg/cli"
configcli "github.com/vmware-tanzu/tanzu-cli/pkg/config"
"github.com/vmware-tanzu/tanzu-cli/pkg/constants"
)

Expand Down Expand Up @@ -713,14 +712,8 @@ func TestEnvVarsSet(t *testing.T) {
os.Setenv("TANZU_CLI_EULA_PROMPT_ANSWER", "Yes")
defer os.RemoveAll(configFileNG.Name())

// Setup default feature flags since we have created new config files
// TODO(khouzam): This is because AddDefaultFeatureFlagsIfMissing() has already
// been called in an init() function. We should fix that in a more generic way.
c, err := config.GetClientConfigNoLock()
err := config.ConfigureFeatureFlags(constants.DefaultCliFeatureFlags)
assert.Nil(err)
if configcli.AddDefaultFeatureFlagsIfMissing(c, constants.DefaultCliFeatureFlags) {
_ = config.StoreClientConfig(c)
}

rootCmd, err := NewRootCmd()
assert.Nil(err)
Expand Down
38 changes: 38 additions & 0 deletions pkg/config/context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2024 VMware, Inc. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package config

import (
"github.com/pkg/errors"

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

// SyncContextsAndServers populate or sync contexts and servers
func SyncContextsAndServers() error {
cfg, err := config.GetClientConfig()
if err != nil {
return errors.Wrap(err, "failed to get client config")
}

config.PopulateContexts(cfg)

// Now write the context to the configuration file. This will also create any missing server for its corresponding context
for _, c := range cfg.KnownContexts {
err := config.SetContext(c, false)
if err != nil {
return errors.Wrap(err, "failed to set context")
}
}

// Now write the active contexts to the configuration file. This will also create any missing active server for its corresponding context
activeContexts, _ := cfg.GetAllActiveContextsList()
for _, c := range activeContexts {
err := config.SetActiveContext(c)
if err != nil {
return errors.Wrap(err, "failed to set active context")
}
}
return nil
}
6 changes: 0 additions & 6 deletions pkg/config/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@ var (
DefaultStandaloneDiscoveryLocalPath = ""
)

// CoreRepositoryName is the core repository name.
const CoreRepositoryName = "core"

// CoreBucketName is the name of the core plugin repository bucket to use.
var CoreBucketName = "tanzu-cli-framework"

// DefaultTMCPluginsArtifactRepository is the S3 bucket repository for TMC plugins.
const DefaultTMCPluginsArtifactRepository = "https://tmc-cli.s3-us-west-2.amazonaws.com/plugins/artifacts"

Expand Down
Loading

0 comments on commit 3e6a2fb

Please sign in to comment.