Skip to content

Commit

Permalink
Add config prioritizing standalone over context (vmware-tanzu#256)
Browse files Browse the repository at this point in the history
Fixes vmware-tanzu#255

This config allows testing a specific version of a plugin without having
a context replace it with its recommended version.

Signed-off-by: Marc Khouzam <kmarc@vmware.com>
  • Loading branch information
marckhouzam authored and vuil committed May 16, 2023
1 parent aad175f commit a11038f
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 62 deletions.
24 changes: 23 additions & 1 deletion docs/plugindev/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,12 +265,34 @@ as it would introduce a security risk.

### Testing the plugins

#### Manual testing

As a plugin developer, you will want to test your plugin manually at some point.
During the development cycle, you can easily build and install the latest version of your plugin
as described in the section on [building a plugin](#building-a-plugin).

If you are using "contexts" while doing testing of your plugin and that your plugin is context-scoped
you may find that your new plugin version is being overwritten with an older version by the CLI.
When a plugin is context-scoped a context may recommend a specific version of that plugin for the CLI
to use. In such a case, if you want to test your new version and prevent the CLI from overwriting it
with the version recommended by the context you can enable the `TANZU_CLI_STANDALONE_OVER_CONTEXT_PLUGINS`
variable by doing:

```sh
tanzu config set env.TANZU_CLI_STANDALONE_OVER_CONTEXT_PLUGINS true
```

This variable will instruct the CLI that any installation done with `tanzu plugin install <pluginName>`
should take precedence over any installation coming from a context.

#### Automated tests using the test plugin

Plugin tests can be run by installing the admin `test` plugin.
Currently, we only support testing plugins built locally.

**Note:** The `test` admin functionality has been deprecated and no future enhancements are planned for this plugin.

Steps to test plugin :-
Steps to test a plugin:

1. Bootstrap a new plugin
2. Build a plugin binary
Expand Down
1 change: 1 addition & 0 deletions pkg/constants/env_variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const (
AllowedRegistries = "ALLOWED_REGISTRY"
ConfigVariableAdditionalDiscoveryForTesting = "TANZU_CLI_ADDITIONAL_PLUGIN_DISCOVERY_IMAGES_TEST_ONLY"
ConfigVariableIncludeDeactivatedPluginsForTesting = "TANZU_CLI_INCLUDE_DEACTIVATED_PLUGINS_TEST_ONLY"
ConfigVariableStandaloneOverContextPlugins = "TANZU_CLI_STANDALONE_OVER_CONTEXT_PLUGINS"
// PluginDiscoveryImageSignatureVerificationSkipList is a comma separated list of discovery image urls
PluginDiscoveryImageSignatureVerificationSkipList = "TANZU_CLI_PLUGIN_DISCOVERY_IMAGE_SIGNATURE_VERIFICATION_SKIP_LIST"
PublicKeyPathForPluginDiscoveryImageSignature = "TANZU_CLI_PLUGIN_DISCOVERY_IMAGE_SIGNATURE_PUBLIC_KEY_PATH"
Expand Down
92 changes: 62 additions & 30 deletions pkg/pluginsupplier/plugin_supplier.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
package pluginsupplier

import (
"os"
"strconv"

"github.com/vmware-tanzu/tanzu-cli/pkg/catalog"
"github.com/vmware-tanzu/tanzu-cli/pkg/cli"
"github.com/vmware-tanzu/tanzu-cli/pkg/constants"
configlib "github.com/vmware-tanzu/tanzu-plugin-runtime/config"
)

Expand All @@ -27,62 +31,90 @@ func GetInstalledPlugins() ([]cli.PluginInfo, error) {

// GetInstalledStandalonePlugins returns the installed standalone plugins.
func GetInstalledStandalonePlugins() ([]cli.PluginInfo, error) {
standAloneCatalog, err := catalog.NewContextCatalog("")
standalonePlugins, _, err := getInstalledStandaloneAndServerPlugins()
if err != nil {
return nil, err
}
plugins := standAloneCatalog.List()
return standalonePlugins, nil
}

// Any server plugin installed takes precedence over the same plugin
// installed as standalone. We therefore remove those standalone
// plugins from the list.
plugins, err = removeInstalledServerPlugins(plugins)
// GetInstalledServerPlugins returns the installed server plugins.
func GetInstalledServerPlugins() ([]cli.PluginInfo, error) {
_, serverPlugins, err := getInstalledStandaloneAndServerPlugins()
if err != nil {
return nil, err
}
return plugins, nil
return serverPlugins, nil
}

// GetInstalledServerPlugins returns the installed server plugins.
func GetInstalledServerPlugins() ([]cli.PluginInfo, error) {
serverNames, err := configlib.GetAllCurrentContextsList()
func getInstalledStandaloneAndServerPlugins() (standalonePlugins, serverPlugins []cli.PluginInfo, err error) {
// Get all the standalone plugins found in the catalog
standAloneCatalog, err := catalog.NewContextCatalog("")
if err != nil {
return nil, err
return nil, nil, err
}
standalonePlugins = standAloneCatalog.List()

var serverPlugins []cli.PluginInfo
// Get all the server plugins found in the catalog
serverNames, err := configlib.GetAllCurrentContextsList()
if err != nil {
return nil, nil, err
}
for _, serverName := range serverNames {
if serverName != "" {
serverCatalog, err := catalog.NewContextCatalog(serverName)
if err != nil {
return nil, err
return nil, nil, err
}
serverPlugins = append(serverPlugins, serverCatalog.List()...)
}
}

return serverPlugins, nil
// If the same plugin is present both as standalone and
// as a server plugin we need to select which one to use
// based on the TANZU_CLI_STANDALONE_OVER_CONTEXT_PLUGINS variable
standalonePlugins, serverPlugins = filterIdenticalStandaloneAndServerPlugins(standalonePlugins, serverPlugins)
return standalonePlugins, serverPlugins, nil
}

// Remove any installed standalone plugin if it is also installed as a server plugin.
func removeInstalledServerPlugins(standalone []cli.PluginInfo) ([]cli.PluginInfo, error) {
serverPlugins, err := GetInstalledServerPlugins()
if err != nil {
return nil, err
}
// Remove an installed standalone plugin if it is also installed as a server plugin,
// or vice versa if the TANZU_CLI_STANDALONE_OVER_CONTEXT_PLUGINS variable is enabled
func filterIdenticalStandaloneAndServerPlugins(standalonePlugins, serverPlugins []cli.PluginInfo) (installedStandalone, installedServer []cli.PluginInfo) {
standaloneOverServerPlugins, _ := strconv.ParseBool(os.Getenv(constants.ConfigVariableStandaloneOverContextPlugins))

var installedStandalone []cli.PluginInfo
for i := range standalone {
found := false
for j := range serverPlugins {
if standalone[i].Name == serverPlugins[j].Name && standalone[i].Target == serverPlugins[j].Target {
found = true
break
if !standaloneOverServerPlugins {
installedServer = serverPlugins

for i := range standalonePlugins {
found := false
for j := range serverPlugins {
if standalonePlugins[i].Name == serverPlugins[j].Name && standalonePlugins[i].Target == serverPlugins[j].Target {
found = true
break
}
}
if !found {
// No server plugin of the same name/target so we keep the standalone plugin
installedStandalone = append(installedStandalone, standalonePlugins[i])
}
}
if !found {
installedStandalone = append(installedStandalone, standalone[i])
} else {
installedStandalone = standalonePlugins

for i := range serverPlugins {
found := false
for j := range standalonePlugins {
if serverPlugins[i].Name == standalonePlugins[j].Name && serverPlugins[i].Target == standalonePlugins[j].Target {
found = true
break
}
}
if !found {
// No standalone plugin of the same name/target so we keep the server plugin
installedServer = append(installedServer, serverPlugins[i])
}
}
}
return installedStandalone, nil

return installedStandalone, installedServer
}
Loading

0 comments on commit a11038f

Please sign in to comment.