Skip to content

Commit

Permalink
Sync Single Target Plugins Only
Browse files Browse the repository at this point in the history
This pull request updates existing functionality of context create/use as follows:

1. 'tanzu context create' now performs 'plugin sync' only for the newly created context, not for all active contexts.

2. 'tanzu context use' now triggers 'plugin sync' only for the context being set as active, not for all currently active contexts.
  • Loading branch information
Chandra Pamuluri committed Oct 19, 2023
1 parent 99094df commit aeaa4ae
Show file tree
Hide file tree
Showing 8 changed files with 460 additions and 54 deletions.
8 changes: 4 additions & 4 deletions pkg/command/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,13 +246,13 @@ func createCtx(_ *cobra.Command, args []string) (err error) {
}

// Sync all required plugins
_ = syncContextPlugins()
_ = syncContextPlugins(ctx.ContextType)

return nil
}

func syncContextPlugins() error {
err := pluginmanager.SyncPlugins()
func syncContextPlugins(contextType configtypes.ContextType) error {
err := pluginmanager.SyncPluginsForContextType(contextType)
if err != nil {
log.Warningf("unable to automatically sync the plugins from target context. Please run 'tanzu plugin sync' command to sync plugins manually, error: '%v'", err.Error())
}
Expand Down Expand Up @@ -1006,7 +1006,7 @@ func useCtx(_ *cobra.Command, args []string) error {
}

// Sync all required plugins
_ = syncContextPlugins()
_ = syncContextPlugins(ctx.ContextType)

return nil
}
Expand Down
59 changes: 51 additions & 8 deletions pkg/pluginmanager/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ const (
missingTargetStr = "unable to uniquely identify plugin '%v'. Please specify the target (" + common.TargetList + ") of the plugin using the `--target` flag"
errorWhileDiscoveringPlugins = "there was an error while discovering plugins, error information: '%v'"
errorNoDiscoverySourcesFound = "there are no plugin discovery sources available. Please run 'tanzu plugin source init'"

errorNoActiveContexForGivenContextType = "there is no active context for the given context type `%v`"
)

var execCommand = exec.Command
Expand Down Expand Up @@ -160,20 +162,27 @@ func GetAdditionalTestPluginDiscoveries() []configtypes.PluginDiscovery {
return testDiscoveries
}

// DiscoverServerPlugins returns the available plugins associated all the active contexts
// DiscoverServerPlugins returns the available discovered plugins associated with all active contexts
func DiscoverServerPlugins() ([]discovery.Discovered, error) {
var plugins []discovery.Discovered
var errList []error

currentContextMap, err := configlib.GetAllActiveContextsMap()
if err != nil {
return nil, err
}
if len(currentContextMap) == 0 {
return plugins, nil
contexts := make([]*configtypes.Context, 0)
for _, context := range currentContextMap {
contexts = append(contexts, context)
}
return DiscoverServerPluginsForGivenContexts(contexts)
}

for _, context := range currentContextMap {
// DiscoverServerPluginsForGivenContexts returns the available discovered plugins associated with specific contexts
func DiscoverServerPluginsForGivenContexts(contexts []*configtypes.Context) ([]discovery.Discovered, error) {
var plugins []discovery.Discovered
var errList []error
if len(contexts) == 0 {
return plugins, nil
}
for _, context := range contexts {
var discoverySources []configtypes.PluginDiscovery
discoverySources = append(discoverySources, context.DiscoverySources...)
discoverySources = append(discoverySources, defaultDiscoverySourceBasedOnContext(context)...)
Expand Down Expand Up @@ -990,7 +999,41 @@ func SyncPlugins() error {
if err != nil {
errList = append(errList, err)
}
if installedPlugins, err := pluginsupplier.GetInstalledServerPlugins(); err == nil {
err = installDiscoveredContextPlugins(plugins)
if err != nil {
errList = append(errList, err)
}
return kerrors.NewAggregate(errList)
}

// SyncPluginsForContextType installs the plugins for given ContextType
func SyncPluginsForContextType(contextType configtypes.ContextType) error {
ctx, err := configlib.GetActiveContext(contextType)
if err != nil {
return err
}
if ctx == nil {
return fmt.Errorf(errorNoActiveContexForGivenContextType, contextType)
}
log.Infof("Checking for required plugins for context %s...", ctx.Name)
errList := make([]error, 0)
plugins, err := DiscoverServerPluginsForGivenContexts([]*configtypes.Context{ctx})
if err != nil {
errList = append(errList, err)
}
err = installDiscoveredContextPlugins(plugins)
if err != nil {
errList = append(errList, err)
}
return kerrors.NewAggregate(errList)
}

// installDiscoveredContextPlugins installs the given context scope plugins
func installDiscoveredContextPlugins(plugins []discovery.Discovered) error {
var errList []error
var err error
var installedPlugins []cli.PluginInfo
if installedPlugins, err = pluginsupplier.GetInstalledServerPlugins(); err == nil {
setAvailablePluginsStatus(plugins, installedPlugins)
}

Expand Down
85 changes: 85 additions & 0 deletions pkg/pluginmanager/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"

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

"github.com/vmware-tanzu/tanzu-cli/pkg/cli"
Expand Down Expand Up @@ -673,6 +674,90 @@ func Test_SyncPlugins(t *testing.T) {
}
}

// TestSyncPluginsForK8SSpecificContextType tests to sync plugins for k8s specific ContextType only
func TestSyncPluginsForK8SSpecificContextType(t *testing.T) {
assertions := assert.New(t)
ctx, err := configlib.GetActiveContext("k8s")
fmt.Println(ctx, err)
defer setupPluginSourceForTesting()()
execCommand = fakeInfoExecCommand
defer func() { execCommand = exec.Command }()

// Get the server plugins (they are not installed yet)
serverPlugins, err := DiscoverServerPlugins()
assertions.NotNil(err)
// There is an error for the kubernetes discovery since we don't have a cluster
// but other server plugins will be found, so we use those
assertions.Contains(err.Error(), `Failed to load Kubeconfig file from "config"`)
assertions.Equal(len(expectedDiscoveredContextPlugins), len(serverPlugins))
var k8sContextPlugins []*discovery.Discovered
for _, edp := range expectedDiscoveredContextPlugins {
p := findDiscoveredPlugin(serverPlugins, edp.Name, edp.Target)
assertions.NotNil(p)
assertions.Equal(common.PluginStatusNotInstalled, p.Status)
if p.Target == configtypes.TargetK8s {
k8sContextPlugins = append(k8sContextPlugins, p)
}
}

// Sync all available plugins
err = SyncPluginsForContextType(configtypes.ContextTypeK8s)
assertions.NotNil(err)
// There is an error for the kubernetes discovery since we don't have a cluster
// but other server plugins will be found, so we use those
assertions.Contains(err.Error(), `Failed to load Kubeconfig file from "config"`)

installedServerPlugins, err := pluginsupplier.GetInstalledServerPlugins()
assertions.Nil(err)
assertions.Equal(len(installedServerPlugins), len(k8sContextPlugins))

for _, isp := range installedServerPlugins {
assertions.Equal(isp.Target, configtypes.TargetK8s)
p := findDiscoveredPlugin(serverPlugins, isp.Name, isp.Target)
assertions.NotNil(p)
}
}

// TestSyncPluginsForTMCSpecificContextType tests to sync plugins for tmc specific ContextType only
func TestSyncPluginsForTMCSpecificContextType(t *testing.T) {
assertions := assert.New(t)

defer setupPluginSourceForTesting()()
execCommand = fakeInfoExecCommand
defer func() { execCommand = exec.Command }()

// Get the server plugins (they are not installed yet)
serverPlugins, err := DiscoverServerPlugins()
assertions.NotNil(err)
// There is an error for the kubernetes discovery since we don't have a cluster
// but other server plugins will be found, so we use those
assertions.Contains(err.Error(), `Failed to load Kubeconfig file from "config"`)
assertions.Equal(len(expectedDiscoveredContextPlugins), len(serverPlugins))
var tmcTargetPlugins []*discovery.Discovered
for _, edp := range expectedDiscoveredContextPlugins {
p := findDiscoveredPlugin(serverPlugins, edp.Name, edp.Target)
assertions.NotNil(p)
assertions.Equal(common.PluginStatusNotInstalled, p.Status)
if p.Target == configtypes.TargetTMC {
tmcTargetPlugins = append(tmcTargetPlugins, p)
}
}

// Sync all available plugins
err = SyncPluginsForContextType(configtypes.ContextTypeTMC)
assertions.Nil(err)

installedServerPlugins, err := pluginsupplier.GetInstalledServerPlugins()
assertions.Nil(err)
assertions.Equal(len(installedServerPlugins), len(tmcTargetPlugins))

for _, isp := range installedServerPlugins {
assertions.Equal(isp.Target, configtypes.TargetTMC)
p := findDiscoveredPlugin(serverPlugins, isp.Name, isp.Target)
assertions.NotNil(p)
}
}

func Test_setAvailablePluginsStatus(t *testing.T) {
assertions := assert.New(t)

Expand Down
1 change: 0 additions & 1 deletion test/e2e/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ TANZU_CLI_E2E_AIRGAPPED_REPO_WITH_AUTH_PASSWORD = testpassword
endif



# Set the plugin group name for the plugins used to execute E2E test cases.
E2E_TEST_USE_PLGINS_FROM_PLUGIN_GROUP_FOR_TMC ?= vmware-tmc/tmc-user:v9.9.9
E2E_TEST_USE_PLGINS_FROM_PLUGIN_GROUP_FOR_K8S ?= vmware-tkg/default:v9.9.9
Expand Down
6 changes: 3 additions & 3 deletions test/e2e/framework/context_lifecycle_operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ type ContextCmdOps interface {
ListContext(opts ...E2EOption) ([]*ContextListInfo, error)
// DeleteContext helps to run `context delete` command
DeleteContext(contextName string, opts ...E2EOption) (stdOutStr, stdErrStr string, err error)
// GetActiveContext returns current active context
GetActiveContext(targetType string, opts ...E2EOption) (string, error)
// GetActiveContext returns current active context for given context-type
GetActiveContext(contextType string, opts ...E2EOption) (string, error)
// GetActiveContexts returns all active contexts
GetActiveContexts(opts ...E2EOption) ([]*ContextListInfo, error)
// UnsetContext unsets the given context with 'tanzu context unset' and returns stdOut, stdErr and error
Expand Down Expand Up @@ -103,7 +103,7 @@ func (cc *contextCmdOps) GetActiveContexts(opts ...E2EOption) ([]*ContextListInf
if err != nil {
return contexts, err
}
for i, _ := range list {
for i := range list {
if list[i].Iscurrent == True {
contexts = append(contexts, list[i])
}
Expand Down
6 changes: 3 additions & 3 deletions test/e2e/framework/framework_constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,14 @@ const (
Config = "config"
TanzuCLIE2ETestBinaryPath = "TANZU_CLI_E2E_TEST_BINARY_PATH"
WiredMockHTTPServerStartCmd = "docker run --rm -d -p 8080:8080 -p 8443:8443 --name %s -v %s:/home/wiremock rodolpheche/wiremock:2.25.1"
HttpMockServerStopCmd = "docker container stop %s"
HttpMockServerName = "wiremock"
HTTPMockServerStopCmd = "docker container stop %s"
HTTPMockServerName = "wiremock"
defaultTimeout = 5 * time.Second

TMCEndpointForPlugins = "/v1alpha1/system/binaries/plugins"
TMCMockServerEndpoint = "http://localhost:8080"
TMCPluginsMockServerEndpoint = "http://localhost:8080/v1alpha1/system/binaries/plugins"
HttpContentType = "application/json; charset=utf-8"
HTTPContentType = "application/json; charset=utf-8"

// k8s CRD file
K8SCRDFilePath = "../../framework/config/cli.tanzu.vmware.com_cliplugins.yaml"
Expand Down
12 changes: 6 additions & 6 deletions test/e2e/framework/framework_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ func StartMockServer(tf *Framework, mappingDir, containerName string) error {

// StopContainer stops the given docker container
func StopContainer(tf *Framework, containerName string) error {
cmd := fmt.Sprintf(HttpMockServerStopCmd, containerName)
cmd := fmt.Sprintf(HTTPMockServerStopCmd, containerName)
_, _, err := tf.Exec.Exec(cmd)
return err
}
Expand All @@ -420,7 +420,7 @@ func ConvertPluginsInfoToTMCEndpointMockResponse(plugins []*PluginInfo) (*TMCPlu
tmcPlugins := &TMCPluginsResponse{}
tmcPlugins.PluginsInfo = TMCPluginsInfo{}
tmcPlugins.PluginsInfo.Plugins = make([]TMCPlugin, 0)
for i, _ := range plugins {
for i := range plugins {
tmcPlugin := TMCPlugin{}
tmcPlugin.Name = plugins[i].Name
tmcPlugin.Description = plugins[i].Description
Expand All @@ -431,8 +431,8 @@ func ConvertPluginsInfoToTMCEndpointMockResponse(plugins []*PluginInfo) (*TMCPlu
m.Request.Method = "GET"
m.Request.URL = TMCEndpointForPlugins
m.Response.Status = 200
m.Response.Headers.ContentType = HttpContentType
m.Response.Headers.Accept = HttpContentType
m.Response.Headers.ContentType = HTTPContentType
m.Response.Headers.Accept = HTTPContentType
content, err := json.Marshal(tmcPlugins.PluginsInfo)
if err != nil {
log.Error(err, "error while processing input type to json")
Expand Down Expand Up @@ -521,8 +521,8 @@ func GetHTTPCall(url string, v interface{}) error {
if err != nil {
return err
}
req.Header.Set("Content-Type", HttpContentType)
req.Header.Set("Accept", HttpContentType)
req.Header.Set("Content-Type", HTTPContentType)
req.Header.Set("Accept", HTTPContentType)
client := &http.Client{}
response, err := client.Do(req)
if err != nil {
Expand Down
Loading

0 comments on commit aeaa4ae

Please sign in to comment.