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 as follows:

1. For 'tanzu plugin sync', a new optional '--target' parameter has been added. If a user provides a value for '--target', the sync operation is performed only for the specified target, not for all active contexts.

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

3. '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 13, 2023
1 parent b0f029a commit 804e3f1
Show file tree
Hide file tree
Showing 7 changed files with 327 additions and 16 deletions.
8 changes: 4 additions & 4 deletions pkg/command/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,13 +245,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 @@ -995,7 +995,7 @@ func useCtx(_ *cobra.Command, args []string) error {
}

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

return nil
}
Expand Down
14 changes: 13 additions & 1 deletion pkg/command/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ var (

const (
invalidTargetMsg = "invalid target specified. Please specify a correct value for the `--target/-t` flag from '" + common.TargetList + "'"
invalidContextTypeMsg = "invalid contextType specified. Please specify a correct value for the `--contextType/-ct` flag from '" + common.ContextTypeList + "'"
errorWhileDiscoveringPlugins = "there was an error while discovering plugins, error information: '%v'"
errorWhileGettingContextPlugins = "there was an error while getting installed context plugins, error information: '%v'"
pluginNameCaps = "PLUGIN_NAME"
Expand Down Expand Up @@ -108,6 +109,9 @@ func newPluginCmd() *cobra.Command {
describePluginCmd.Flags().StringVarP(&targetStr, "target", "t", "", targetFlagDesc)
utils.PanicOnErr(describePluginCmd.RegisterFlagCompletionFunc("target", completeTargets))

contextTypeFlagDescForSync := fmt.Sprintf("sync plugins only for specific ContextType (%s)", common.ContextTypeList)
syncPluginCmd.Flags().StringVarP(&contextTypeStr, "type", "t", "", contextTypeFlagDescForSync)

installPluginCmd.MarkFlagsMutuallyExclusive("group", "local")
installPluginCmd.MarkFlagsMutuallyExclusive("group", "local-source")
installPluginCmd.MarkFlagsMutuallyExclusive("group", "version")
Expand Down Expand Up @@ -402,7 +406,15 @@ func newSyncPluginCmd() *cobra.Command {
Plugins installed with this command will only be available while the context remains active.`,
ValidArgsFunction: cobra.NoFileCompletions,
RunE: func(cmd *cobra.Command, args []string) (err error) {
err = pluginmanager.SyncPlugins()
if contextTypeStr != "" {
if !configtypes.IsValidContextType(contextTypeStr) {
return errors.New(invalidContextTypeMsg)
}
err = pluginmanager.SyncPluginsForContextType(getContextType())
} else {
err = pluginmanager.SyncPlugins()
}

if err != nil {
return err
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ const (

// Shared strings
const (
TargetList = "kubernetes[k8s]/mission-control[tmc]/global"
TargetList = "kubernetes[k8s]/mission-control[tmc]/global"
ContextTypeList = "kubernetes[k8s]/mission-control[tmc]/application-engine[tae]"
)

// CoreName is the name of the core binary.
Expand Down
58 changes: 50 additions & 8 deletions pkg/pluginmanager/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,20 +160,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 @@ -989,7 +996,42 @@ 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 {
currentContextMap, err := configlib.GetAllActiveContextsMap()
if err != nil {
return err
}
ctx, ok := currentContextMap[contextType]
if !ok {
return fmt.Errorf("there is no active context for the contextType %v ", 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
81 changes: 81 additions & 0 deletions pkg/pluginmanager/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,87 @@ func Test_SyncPlugins(t *testing.T) {
}
}

// Test_SyncPlugins_ForK8SSpecificTarget tests to sync plugins for k8s specific ContextType only
func Test_SyncPlugins_ForK8SSpecificContextType(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 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 {
p := findDiscoveredPlugin(serverPlugins, isp.Name, isp.Target)
assertions.NotNil(p)
}
}

// Test_SyncPlugins_ForTMCSpecificContextType tests to sync plugins for tmc specific ContextType only
func Test_SyncPlugins_ForTMCSpecificContextType(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 {
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
Loading

0 comments on commit 804e3f1

Please sign in to comment.