Skip to content

Commit

Permalink
Support Activating plugins on Plugin Group Publish/Activation (#794)
Browse files Browse the repository at this point in the history
* Support activating plugins on plugin group publish
  • Loading branch information
anujc25 authored Jul 16, 2024
1 parent d4ed21c commit 9451a9a
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 21 deletions.
4 changes: 4 additions & 0 deletions pkg/constants/env_variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,8 @@ const (
// UseStableKubeContextNameForTanzuContext uses the stable kube context name associated with tanzu context.
// CLI would not change the context name when the TAP resource pointed by the CLI context is changed.
UseStableKubeContextNameForTanzuContext = "TANZU_CLI_USE_STABLE_KUBE_CONTEXT_NAME"

// ActivatePluginsOnPluginGroupPublish activates all the plugins specified within the plugin group
// as part of the plugin group publishing
ActivatePluginsOnPluginGroupPublish = "TANZU_CLI_ACTIVATE_PLUGINS_ON_PLUGIN_GROUP_PUBLISH"
)
59 changes: 48 additions & 11 deletions pkg/plugininventory/sqlite_inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ func (b *SQLiteInventory) InsertPlugin(pluginInventoryEntry *PluginInventoryEntr

// InsertPluginGroup inserts plugin-group to the inventory
// specifying override will delete the existing plugin-group and add new one
func (b *SQLiteInventory) InsertPluginGroup(pg *PluginGroup, override bool) error {
func (b *SQLiteInventory) InsertPluginGroup(pg *PluginGroup, override bool) error { //nolint:gocyclo
db, err := sql.Open("sqlite", b.inventoryFile)
if err != nil {
return errors.Wrapf(err, "failed to open the DB from '%s' file", b.inventoryFile)
Expand Down Expand Up @@ -674,7 +674,14 @@ func (b *SQLiteInventory) InsertPluginGroup(pg *PluginGroup, override bool) erro
}
}

allowHiddenPlugins, _ := strconv.ParseBool(os.Getenv(constants.ConfigVariableIncludeDeactivatedPluginsForTesting))
includeDeactivatedPluginsForTesting, _ := strconv.ParseBool(os.Getenv(constants.ConfigVariableIncludeDeactivatedPluginsForTesting))
// Only activate plugins if TANZU_CLI_ACTIVATE_PLUGINS_ON_PLUGIN_GROUP_PUBLISH=true and we are PluginGroup is also active (!pg.Hidden)
activatePlugins, _ := strconv.ParseBool(os.Getenv(constants.ActivatePluginsOnPluginGroupPublish))
activatePlugins = activatePlugins && !pg.Hidden

// Allow hidden plugins if either of the below configuration is specified
allowHiddenPlugins := includeDeactivatedPluginsForTesting || activatePlugins

for version, plugins := range pg.Versions {
for _, pi := range plugins {
// Skip plugin group verification. If TANZU_CLI_SKIP_PLUGIN_GROUP_VERIFICATION_ON_PUBLISH is set while publishing a plugin-group
Expand All @@ -692,6 +699,16 @@ func (b *SQLiteInventory) InsertPluginGroup(pg *PluginGroup, override bool) erro
}
}

// Activate plugins on plugin group publish if the TANZU_CLI_ACTIVATE_PLUGINS_ON_PLUGIN_GROUP_PUBLISH
// environment variable is set to True.
// Note: If it is set to false, plugins won't be deactivated
if activatePlugins {
err = b.updatePluginVersionActivationState(db, pi.Name, string(pi.Target), pi.Version, true)
if err != nil {
return errors.Wrap(err, "unable to activate plugin with in plugin group")
}
}

row := groupDBRow{
vendor: pg.Vendor,
publisher: pg.Publisher,
Expand Down Expand Up @@ -724,18 +741,25 @@ func (b *SQLiteInventory) UpdatePluginActivationState(pluginInventoryEntry *Plug
defer db.Close()

for version := range pluginInventoryEntry.Artifacts {
result, err := db.Exec("UPDATE PluginBinaries SET hidden = ? WHERE PluginName = ? AND Target = ? AND Version = ? AND Publisher = ? AND Vendor = ? ;", strconv.FormatBool(pluginInventoryEntry.Hidden), pluginInventoryEntry.Name, string(pluginInventoryEntry.Target), version, pluginInventoryEntry.Publisher, pluginInventoryEntry.Vendor)
err := b.updatePluginVersionActivationState(db, pluginInventoryEntry.Name, string(pluginInventoryEntry.Target), version, !pluginInventoryEntry.Hidden)
if err != nil {
return errors.Wrapf(err, "unable to update plugin %v_%v", pluginInventoryEntry.Name, string(pluginInventoryEntry.Target))
return err
}
rowsAffected, _ := result.RowsAffected()
if rowsAffected == 0 {
return errors.Errorf("unable to update plugin %v_%v", pluginInventoryEntry.Name, string(pluginInventoryEntry.Target))
}
// Write sql statement logs if required
writeSQLStatementLogs(fmt.Sprintf("UPDATE PluginBinaries SET hidden = %v WHERE PluginName = %v AND Target = %v AND Version = %v AND Publisher = %v AND Vendor = %v ;\n", strconv.FormatBool(pluginInventoryEntry.Hidden), pluginInventoryEntry.Name, string(pluginInventoryEntry.Target), version, pluginInventoryEntry.Publisher, pluginInventoryEntry.Vendor))
}
return nil
}

func (b *SQLiteInventory) updatePluginVersionActivationState(db *sql.DB, name, target, version string, activate bool) error {
result, err := db.Exec("UPDATE PluginBinaries SET hidden = ? WHERE PluginName = ? AND Target = ? AND Version = ? ;", strconv.FormatBool(!activate), name, target, version)
if err != nil {
return errors.Wrapf(err, "unable to update plugin %v_%v", name, target)
}
rowsAffected, _ := result.RowsAffected()
if rowsAffected == 0 {
return errors.Errorf("unable to update plugin %v_%v", name, target)
}
// Write sql statement logs if required
writeSQLStatementLogs(fmt.Sprintf("UPDATE PluginBinaries SET hidden = %v WHERE PluginName = %v AND Target = %v AND Version = %v ;\n", strconv.FormatBool(!activate), name, target, version))
return nil
}

Expand All @@ -746,7 +770,20 @@ func (b *SQLiteInventory) UpdatePluginGroupActivationState(pg *PluginGroup) erro
}
defer db.Close()

for version := range pg.Versions {
activatePlugins, _ := strconv.ParseBool(os.Getenv(constants.ActivatePluginsOnPluginGroupPublish))

for version, plugins := range pg.Versions {
// Activate plugins on plugin group activate if the TANZU_CLI_ACTIVATE_PLUGINS_ON_PLUGIN_GROUP_PUBLISH
// environment variable is set to `True` and we are trying to activate the plugin group
if activatePlugins && !pg.Hidden {
for _, pi := range plugins {
err = b.updatePluginVersionActivationState(db, pi.Name, string(pi.Target), pi.Version, true)
if err != nil {
return errors.Wrap(err, "unable to activate plugin within plugin group")
}
}
}

result, err := db.Exec("UPDATE PluginGroups SET hidden = ? WHERE GroupName = ? AND Publisher = ? AND Vendor = ? AND GroupVersion = ? ;", strconv.FormatBool(pg.Hidden), pg.Name, pg.Publisher, pg.Vendor, version)
if err != nil {
return errors.Wrapf(err, "unable to update plugin-group '%s:%s'", PluginGroupToID(pg), version)
Expand Down
124 changes: 114 additions & 10 deletions pkg/plugininventory/sqlite_inventory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1486,6 +1486,44 @@ var _ = Describe("Unit tests for plugin inventory", func() {
Expect(plugins[0].Version).To(Equal(groupWithHiddenPlugin.Versions["v1.0.0"][0].Version))
Expect(plugins[0].Mandatory).To(Equal(groupWithHiddenPlugin.Versions["v1.0.0"][0].Mandatory))
})
It("should not return error if TANZU_CLI_ACTIVATE_PLUGINS_ON_PLUGIN_GROUP_PUBLISH=true and Plugins should be activated", func() {
err = os.Setenv(constants.ActivatePluginsOnPluginGroupPublish, "true")
defer os.Unsetenv(constants.ActivatePluginsOnPluginGroupPublish)
Expect(err).To(BeNil())

err = inventory.InsertPluginGroup(&groupWithHiddenPlugin, false)
Expect(err).To(BeNil())

groups, err := inventory.GetPluginGroups(PluginGroupFilter{})
Expect(err).ToNot(HaveOccurred())
Expect(len(groups)).To(Equal(1))
pg := groups[0]
Expect(pg.Name).To(Equal(groupWithHiddenPlugin.Name))
Expect(pg.Vendor).To(Equal(groupWithHiddenPlugin.Vendor))
Expect(pg.Publisher).To(Equal(groupWithHiddenPlugin.Publisher))
Expect(pg.Description).To(Equal(groupWithHiddenPlugin.Description))

Expect(pg.Hidden).To(Equal(groupWithHiddenPlugin.Hidden))

Expect(len(pg.Versions)).To(Equal(1))

plugins := pg.Versions["v1.0.0"]
Expect(len(plugins)).To(Equal(1))
Expect(plugins[0].Name).To(Equal(groupWithHiddenPlugin.Versions["v1.0.0"][0].Name))
Expect(plugins[0].Target).To(Equal(groupWithHiddenPlugin.Versions["v1.0.0"][0].Target))
Expect(plugins[0].Version).To(Equal(groupWithHiddenPlugin.Versions["v1.0.0"][0].Version))
Expect(plugins[0].Mandatory).To(Equal(groupWithHiddenPlugin.Versions["v1.0.0"][0].Mandatory))

// Try to get the plugin with IncludeHidden:false filter and verify that
// plugin that was deactivated before creating plugin group is now activated
updatedPlugins, err := inventory.GetPlugins(&PluginInventoryFilter{Name: plugins[0].Name, Target: plugins[0].Target, Version: plugins[0].Version, IncludeHidden: false})
Expect(err).ToNot(HaveOccurred())
Expect(len(updatedPlugins)).To(Equal(1))
Expect(updatedPlugins[0].Name).To(Equal(plugins[0].Name))
Expect(updatedPlugins[0].Target).To(Equal(plugins[0].Target))
Expect(updatedPlugins[0].RecommendedVersion).To(Equal(plugins[0].Version))
Expect(updatedPlugins[0].Hidden).To(BeFalse())
})
})
Context("When inserting a plugin-group which already exists in the database", func() {
BeforeEach(func() {
Expand Down Expand Up @@ -1581,6 +1619,8 @@ var _ = Describe("Unit tests for plugin inventory", func() {
Expect(err).To(BeNil(), "failed to insert plugin2")
err = inventory.InsertPlugin(&piEntry3)
Expect(err).To(BeNil(), "failed to insert plugin3")
err = inventory.InsertPlugin(&hiddenPluginEntry)
Expect(err).To(BeNil(), "failed to insert hidden-plugin")
})
AfterEach(func() {
os.RemoveAll(tmpDir)
Expand All @@ -1591,7 +1631,7 @@ var _ = Describe("Unit tests for plugin inventory", func() {
err = inventory.InsertPluginGroup(&pluginGroup1, false)
Expect(err).To(BeNil())
})
It("should not return error when no change has been done to the activation state and the GetPluginGroups should reflect the same", func() {
It("should not return error when no change has been done to the activation state and plugin group should still be active and the GetPluginGroups should reflect the same", func() {
err = inventory.UpdatePluginGroupActivationState(&pluginGroup1)
Expect(err).To(BeNil())

Expand All @@ -1608,8 +1648,35 @@ var _ = Describe("Unit tests for plugin inventory", func() {
Expect(len(groups[0].Versions["v2.0.0"])).To(Equal(len(pluginGroup1.Versions["v2.0.0"])))
Expect(len(groups[0].Versions["v1.0.0"])).To(Equal(len(pluginGroup1.Versions["v1.0.0"])))
})
It("should not return error when the activation state has been updated and the GetPluginGroups should reflect the change", func() {
It("should not return error when the plugin group is deactivated and the GetPluginGroups should not return the plugin group", func() {
pluginGroupUpdated := pluginGroup1
pluginGroupUpdated.Hidden = true
err = inventory.UpdatePluginGroupActivationState(&pluginGroupUpdated)
Expect(err).To(BeNil())

// Verify the result using GetPluginGroups
groups, err := inventory.GetPluginGroups(PluginGroupFilter{})
Expect(err).ToNot(HaveOccurred())
Expect(len(groups)).To(Equal(0))
})
})

Context("When updating the activation state of a plugin-group wrt TANZU_CLI_ACTIVATE_PLUGINS_ON_PLUGIN_GROUP_PUBLISH env variable", func() {
BeforeEach(func() {
err = os.Setenv(constants.ConfigVariableIncludeDeactivatedPluginsForTesting, "true")
defer os.Unsetenv(constants.ConfigVariableIncludeDeactivatedPluginsForTesting)
hiddenGroupWithHiddenPlugin := groupWithHiddenPlugin
hiddenGroupWithHiddenPlugin.Hidden = true
Expect(err).To(BeNil())
err = inventory.InsertPluginGroup(&hiddenGroupWithHiddenPlugin, false)
Expect(err).To(BeNil())
})
It("when activating plugin group containing a deactivated plugin with TANZU_CLI_ACTIVATE_PLUGINS_ON_PLUGIN_GROUP_PUBLISH=true set, it should activate the deactivated plugin", func() {
err = os.Setenv(constants.ActivatePluginsOnPluginGroupPublish, "true")
defer os.Unsetenv(constants.ActivatePluginsOnPluginGroupPublish)
Expect(err).To(BeNil())

pluginGroupUpdated := groupWithHiddenPlugin
pluginGroupUpdated.Hidden = false
err = inventory.UpdatePluginGroupActivationState(&pluginGroupUpdated)
Expect(err).To(BeNil())
Expand All @@ -1618,14 +1685,51 @@ var _ = Describe("Unit tests for plugin inventory", func() {
groups, err := inventory.GetPluginGroups(PluginGroupFilter{})
Expect(err).ToNot(HaveOccurred())
Expect(len(groups)).To(Equal(1))
Expect(groups[0].Name).To(Equal(pluginGroupUpdated.Name))
Expect(groups[0].Vendor).To(Equal(pluginGroupUpdated.Vendor))
Expect(groups[0].Publisher).To(Equal(pluginGroupUpdated.Publisher))
Expect(groups[0].Description).To(Equal(pluginGroupUpdated.Description))
Expect(groups[0].Hidden).To(Equal(pluginGroupUpdated.Hidden))
Expect(len(groups[0].Versions)).To(Equal(len(pluginGroup1.Versions)))
Expect(len(groups[0].Versions["v2.0.0"])).To(Equal(len(pluginGroup1.Versions["v2.0.0"])))
Expect(len(groups[0].Versions["v1.0.0"])).To(Equal(len(pluginGroup1.Versions["v1.0.0"])))
pg := groups[0]
// Make sure the hidden field is set to correct value we requested
Expect(pg.Hidden).To(Equal(groupWithHiddenPlugin.Hidden))
Expect(len(pg.Versions)).To(Equal(1))

plugins := pg.Versions["v1.0.0"]
Expect(len(plugins)).To(Equal(1))
Expect(plugins[0].Name).To(Equal(groupWithHiddenPlugin.Versions["v1.0.0"][0].Name))
Expect(plugins[0].Target).To(Equal(groupWithHiddenPlugin.Versions["v1.0.0"][0].Target))
Expect(plugins[0].Version).To(Equal(groupWithHiddenPlugin.Versions["v1.0.0"][0].Version))
Expect(plugins[0].Mandatory).To(Equal(groupWithHiddenPlugin.Versions["v1.0.0"][0].Mandatory))

// Try to get the plugin with IncludeHidden:false filter and verify that
// plugin that was deactivated before activating the plugin group is not activated
updatedPlugins, err := inventory.GetPlugins(&PluginInventoryFilter{Name: plugins[0].Name, Target: plugins[0].Target, Version: plugins[0].Version, IncludeHidden: false})
Expect(err).ToNot(HaveOccurred())
Expect(len(updatedPlugins)).To(Equal(1))
Expect(updatedPlugins[0].Name).To(Equal(plugins[0].Name))
Expect(updatedPlugins[0].Target).To(Equal(plugins[0].Target))
Expect(updatedPlugins[0].RecommendedVersion).To(Equal(plugins[0].Version))
Expect(updatedPlugins[0].Hidden).To(BeFalse())
})
It("when activating plugin group containing a deactivated plugin without TANZU_CLI_ACTIVATE_PLUGINS_ON_PLUGIN_GROUP_PUBLISH being set, it should NOT activate the deactivated plugin", func() {
pluginGroupUpdated := groupWithHiddenPlugin
pluginGroupUpdated.Hidden = false
err = inventory.UpdatePluginGroupActivationState(&pluginGroupUpdated)
Expect(err).To(BeNil())

// Verify the result using GetPluginGroups
groups, err := inventory.GetPluginGroups(PluginGroupFilter{})
Expect(err).ToNot(HaveOccurred())
Expect(len(groups)).To(Equal(1))
pg := groups[0]

plugins := pg.Versions["v1.0.0"]
Expect(len(plugins)).To(Equal(1))
Expect(plugins[0].Name).To(Equal(groupWithHiddenPlugin.Versions["v1.0.0"][0].Name))
Expect(plugins[0].Target).To(Equal(groupWithHiddenPlugin.Versions["v1.0.0"][0].Target))
Expect(plugins[0].Version).To(Equal(groupWithHiddenPlugin.Versions["v1.0.0"][0].Version))
Expect(plugins[0].Mandatory).To(Equal(groupWithHiddenPlugin.Versions["v1.0.0"][0].Mandatory))

// Try to get the plugin with IncludeHidden:false filter and no plugins should be present
plugins2, err := inventory.GetPlugins(&PluginInventoryFilter{Name: plugins[0].Name, Target: plugins[0].Target, Version: plugins[0].Version, IncludeHidden: false})
Expect(err).ToNot(HaveOccurred())
Expect(len(plugins2)).To(Equal(0))
})
})

Expand Down

0 comments on commit 9451a9a

Please sign in to comment.