Split plugin commands into individual files
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
This commit is contained in:
@@ -18,7 +18,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -26,7 +25,6 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/fluxcd/flux2/v2/internal/plugin"
|
"github.com/fluxcd/flux2/v2/internal/plugin"
|
||||||
"github.com/fluxcd/flux2/v2/pkg/printers"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var pluginHandler = plugin.NewHandler()
|
var pluginHandler = plugin.NewHandler()
|
||||||
@@ -41,66 +39,7 @@ var pluginCmd = &cobra.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var pluginListCmd = &cobra.Command{
|
|
||||||
Use: "list",
|
|
||||||
Aliases: []string{"ls"},
|
|
||||||
Short: "List installed plugins",
|
|
||||||
Long: `The plugin list command shows all installed plugins with their versions and paths.`,
|
|
||||||
RunE: pluginListCmdRun,
|
|
||||||
}
|
|
||||||
|
|
||||||
var pluginInstallCmd = &cobra.Command{
|
|
||||||
Use: "install <name>[@<version>]",
|
|
||||||
Short: "Install a plugin from the catalog",
|
|
||||||
Long: `The plugin install command downloads and installs a plugin from the Flux plugin catalog.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
# Install the latest version
|
|
||||||
flux plugin install operator
|
|
||||||
|
|
||||||
# Install a specific version
|
|
||||||
flux plugin install operator@0.45.0`,
|
|
||||||
Args: cobra.ExactArgs(1),
|
|
||||||
RunE: pluginInstallCmdRun,
|
|
||||||
}
|
|
||||||
|
|
||||||
var pluginUninstallCmd = &cobra.Command{
|
|
||||||
Use: "uninstall <name>",
|
|
||||||
Short: "Uninstall a plugin",
|
|
||||||
Long: `The plugin uninstall command removes a plugin binary and its receipt from the plugin directory.`,
|
|
||||||
Args: cobra.ExactArgs(1),
|
|
||||||
RunE: pluginUninstallCmdRun,
|
|
||||||
}
|
|
||||||
|
|
||||||
var pluginUpdateCmd = &cobra.Command{
|
|
||||||
Use: "update [name]",
|
|
||||||
Short: "Update installed plugins",
|
|
||||||
Long: `The plugin update command updates installed plugins to their latest versions.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
# Update a single plugin
|
|
||||||
flux plugin update operator
|
|
||||||
|
|
||||||
# Update all installed plugins
|
|
||||||
flux plugin update`,
|
|
||||||
Args: cobra.MaximumNArgs(1),
|
|
||||||
RunE: pluginUpdateCmdRun,
|
|
||||||
}
|
|
||||||
|
|
||||||
var pluginSearchCmd = &cobra.Command{
|
|
||||||
Use: "search [query]",
|
|
||||||
Short: "Search the plugin catalog",
|
|
||||||
Long: `The plugin search command lists available plugins from the Flux plugin catalog.`,
|
|
||||||
Args: cobra.MaximumNArgs(1),
|
|
||||||
RunE: pluginSearchCmdRun,
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
pluginCmd.AddCommand(pluginListCmd)
|
|
||||||
pluginCmd.AddCommand(pluginInstallCmd)
|
|
||||||
pluginCmd.AddCommand(pluginUninstallCmd)
|
|
||||||
pluginCmd.AddCommand(pluginUpdateCmd)
|
|
||||||
pluginCmd.AddCommand(pluginSearchCmd)
|
|
||||||
rootCmd.AddCommand(pluginCmd)
|
rootCmd.AddCommand(pluginCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,173 +88,6 @@ func registerPlugins() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func pluginListCmdRun(cmd *cobra.Command, args []string) error {
|
|
||||||
pluginDir := pluginHandler.PluginDir()
|
|
||||||
plugins := pluginHandler.Discover(builtinCommandNames())
|
|
||||||
if len(plugins) == 0 {
|
|
||||||
cmd.Println("No plugins found")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
header := []string{"NAME", "VERSION", "PATH"}
|
|
||||||
var rows [][]string
|
|
||||||
for _, p := range plugins {
|
|
||||||
version := "manual"
|
|
||||||
if receipt := plugin.ReadReceipt(pluginDir, p.Name); receipt != nil {
|
|
||||||
version = receipt.Version
|
|
||||||
}
|
|
||||||
rows = append(rows, []string{p.Name, version, p.Path})
|
|
||||||
}
|
|
||||||
|
|
||||||
return printers.TablePrinter(header).Print(cmd.OutOrStdout(), rows)
|
|
||||||
}
|
|
||||||
|
|
||||||
func pluginInstallCmdRun(cmd *cobra.Command, args []string) error {
|
|
||||||
nameVersion := args[0]
|
|
||||||
name, version := parseNameVersion(nameVersion)
|
|
||||||
|
|
||||||
catalogClient := newCatalogClient()
|
|
||||||
manifest, err := catalogClient.FetchManifest(name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
pv, err := plugin.ResolveVersion(manifest, version)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
plat, err := plugin.ResolvePlatform(pv, runtime.GOOS, runtime.GOARCH)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("plugin %q v%s has no binary for %s/%s", name, pv.Version, runtime.GOOS, runtime.GOARCH)
|
|
||||||
}
|
|
||||||
|
|
||||||
pluginDir := pluginHandler.EnsurePluginDir()
|
|
||||||
|
|
||||||
installer := plugin.NewInstaller()
|
|
||||||
sp := newPluginSpinner(fmt.Sprintf("installing %s v%s", name, pv.Version))
|
|
||||||
sp.Start()
|
|
||||||
if err := installer.Install(pluginDir, manifest, pv, plat); err != nil {
|
|
||||||
sp.Stop()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
sp.Stop()
|
|
||||||
|
|
||||||
logger.Successf("installed %s v%s", name, pv.Version)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func pluginUninstallCmdRun(cmd *cobra.Command, args []string) error {
|
|
||||||
name := args[0]
|
|
||||||
pluginDir := pluginHandler.PluginDir()
|
|
||||||
|
|
||||||
if err := plugin.Uninstall(pluginDir, name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Successf("uninstalled %s", name)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func pluginUpdateCmdRun(cmd *cobra.Command, args []string) error {
|
|
||||||
catalogClient := newCatalogClient()
|
|
||||||
|
|
||||||
plugins := pluginHandler.Discover(builtinCommandNames())
|
|
||||||
if len(plugins) == 0 {
|
|
||||||
cmd.Println("No plugins found")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a specific plugin is requested, filter to just that one.
|
|
||||||
if len(args) == 1 {
|
|
||||||
name := args[0]
|
|
||||||
var found bool
|
|
||||||
for _, p := range plugins {
|
|
||||||
if p.Name == name {
|
|
||||||
plugins = []plugin.Plugin{p}
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
return fmt.Errorf("plugin %q is not installed", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pluginDir := pluginHandler.EnsurePluginDir()
|
|
||||||
installer := plugin.NewInstaller()
|
|
||||||
for _, p := range plugins {
|
|
||||||
result := plugin.CheckUpdate(pluginDir, p.Name, catalogClient, runtime.GOOS, runtime.GOARCH)
|
|
||||||
if result.Err != nil {
|
|
||||||
logger.Failuref("error checking %s: %v", p.Name, result.Err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if result.Skipped {
|
|
||||||
if result.SkipReason == plugin.SkipReasonManual {
|
|
||||||
logger.Warningf("skipping %s (%s)", p.Name, result.SkipReason)
|
|
||||||
} else {
|
|
||||||
logger.Successf("%s already up to date (v%s)", p.Name, result.FromVersion)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
sp := newPluginSpinner(fmt.Sprintf("updating %s v%s → v%s", p.Name, result.FromVersion, result.ToVersion))
|
|
||||||
sp.Start()
|
|
||||||
if err := installer.Install(pluginDir, result.Manifest, result.Version, result.Platform); err != nil {
|
|
||||||
sp.Stop()
|
|
||||||
logger.Failuref("error updating %s: %v", p.Name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sp.Stop()
|
|
||||||
logger.Successf("updated %s v%s → v%s", p.Name, result.FromVersion, result.ToVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func pluginSearchCmdRun(cmd *cobra.Command, args []string) error {
|
|
||||||
catalogClient := newCatalogClient()
|
|
||||||
catalog, err := catalogClient.FetchCatalog()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var query string
|
|
||||||
if len(args) == 1 {
|
|
||||||
query = strings.ToLower(args[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
pluginDir := pluginHandler.PluginDir()
|
|
||||||
header := []string{"NAME", "DESCRIPTION", "INSTALLED"}
|
|
||||||
var rows [][]string
|
|
||||||
for _, entry := range catalog.Plugins {
|
|
||||||
if query != "" {
|
|
||||||
if !strings.Contains(strings.ToLower(entry.Name), query) &&
|
|
||||||
!strings.Contains(strings.ToLower(entry.Description), query) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
installed := ""
|
|
||||||
if receipt := plugin.ReadReceipt(pluginDir, entry.Name); receipt != nil {
|
|
||||||
installed = receipt.Version
|
|
||||||
}
|
|
||||||
|
|
||||||
rows = append(rows, []string{entry.Name, entry.Description, installed})
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rows) == 0 {
|
|
||||||
if query != "" {
|
|
||||||
cmd.Printf("No plugins matching %q found in catalog\n", query)
|
|
||||||
} else {
|
|
||||||
cmd.Println("No plugins found in catalog")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return printers.TablePrinter(header).Print(cmd.OutOrStdout(), rows)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseNameVersion splits "operator@0.45.0" into ("operator", "0.45.0").
|
// parseNameVersion splits "operator@0.45.0" into ("operator", "0.45.0").
|
||||||
// If no @ is present, version is empty (latest).
|
// If no @ is present, version is empty (latest).
|
||||||
func parseNameVersion(s string) (string, string) {
|
func parseNameVersion(s string) (string, string) {
|
||||||
|
|||||||
80
cmd/flux/plugin_install.go
Normal file
80
cmd/flux/plugin_install.go
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2026 The Flux authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/fluxcd/flux2/v2/internal/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var pluginInstallCmd = &cobra.Command{
|
||||||
|
Use: "install <name>[@<version>]",
|
||||||
|
Short: "Install a plugin from the catalog",
|
||||||
|
Long: `The plugin install command downloads and installs a plugin from the Flux plugin catalog.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
# Install the latest version
|
||||||
|
flux plugin install operator
|
||||||
|
|
||||||
|
# Install a specific version
|
||||||
|
flux plugin install operator@0.45.0`,
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
RunE: pluginInstallCmdRun,
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
pluginCmd.AddCommand(pluginInstallCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pluginInstallCmdRun(cmd *cobra.Command, args []string) error {
|
||||||
|
nameVersion := args[0]
|
||||||
|
name, version := parseNameVersion(nameVersion)
|
||||||
|
|
||||||
|
catalogClient := newCatalogClient()
|
||||||
|
manifest, err := catalogClient.FetchManifest(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pv, err := plugin.ResolveVersion(manifest, version)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
plat, err := plugin.ResolvePlatform(pv, runtime.GOOS, runtime.GOARCH)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("plugin %q v%s has no binary for %s/%s", name, pv.Version, runtime.GOOS, runtime.GOARCH)
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginDir := pluginHandler.EnsurePluginDir()
|
||||||
|
|
||||||
|
installer := plugin.NewInstaller()
|
||||||
|
sp := newPluginSpinner(fmt.Sprintf("installing %s v%s", name, pv.Version))
|
||||||
|
sp.Start()
|
||||||
|
if err := installer.Install(pluginDir, manifest, pv, plat); err != nil {
|
||||||
|
sp.Stop()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sp.Stop()
|
||||||
|
|
||||||
|
logger.Successf("installed %s v%s", name, pv.Version)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
57
cmd/flux/plugin_list.go
Normal file
57
cmd/flux/plugin_list.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2026 The Flux authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/fluxcd/flux2/v2/internal/plugin"
|
||||||
|
"github.com/fluxcd/flux2/v2/pkg/printers"
|
||||||
|
)
|
||||||
|
|
||||||
|
var pluginListCmd = &cobra.Command{
|
||||||
|
Use: "list",
|
||||||
|
Aliases: []string{"ls"},
|
||||||
|
Short: "List installed plugins",
|
||||||
|
Long: `The plugin list command shows all installed plugins with their versions and paths.`,
|
||||||
|
RunE: pluginListCmdRun,
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
pluginCmd.AddCommand(pluginListCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pluginListCmdRun(cmd *cobra.Command, args []string) error {
|
||||||
|
pluginDir := pluginHandler.PluginDir()
|
||||||
|
plugins := pluginHandler.Discover(builtinCommandNames())
|
||||||
|
if len(plugins) == 0 {
|
||||||
|
cmd.Println("No plugins found")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
header := []string{"NAME", "VERSION", "PATH"}
|
||||||
|
var rows [][]string
|
||||||
|
for _, p := range plugins {
|
||||||
|
version := "manual"
|
||||||
|
if receipt := plugin.ReadReceipt(pluginDir, p.Name); receipt != nil {
|
||||||
|
version = receipt.Version
|
||||||
|
}
|
||||||
|
rows = append(rows, []string{p.Name, version, p.Path})
|
||||||
|
}
|
||||||
|
|
||||||
|
return printers.TablePrinter(header).Print(cmd.OutOrStdout(), rows)
|
||||||
|
}
|
||||||
81
cmd/flux/plugin_search.go
Normal file
81
cmd/flux/plugin_search.go
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2026 The Flux authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/fluxcd/flux2/v2/internal/plugin"
|
||||||
|
"github.com/fluxcd/flux2/v2/pkg/printers"
|
||||||
|
)
|
||||||
|
|
||||||
|
var pluginSearchCmd = &cobra.Command{
|
||||||
|
Use: "search [query]",
|
||||||
|
Short: "Search the plugin catalog",
|
||||||
|
Long: `The plugin search command lists available plugins from the Flux plugin catalog.`,
|
||||||
|
Args: cobra.MaximumNArgs(1),
|
||||||
|
RunE: pluginSearchCmdRun,
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
pluginCmd.AddCommand(pluginSearchCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pluginSearchCmdRun(cmd *cobra.Command, args []string) error {
|
||||||
|
catalogClient := newCatalogClient()
|
||||||
|
catalog, err := catalogClient.FetchCatalog()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var query string
|
||||||
|
if len(args) == 1 {
|
||||||
|
query = strings.ToLower(args[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginDir := pluginHandler.PluginDir()
|
||||||
|
header := []string{"NAME", "DESCRIPTION", "INSTALLED"}
|
||||||
|
var rows [][]string
|
||||||
|
for _, entry := range catalog.Plugins {
|
||||||
|
if query != "" {
|
||||||
|
if !strings.Contains(strings.ToLower(entry.Name), query) &&
|
||||||
|
!strings.Contains(strings.ToLower(entry.Description), query) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
installed := ""
|
||||||
|
if receipt := plugin.ReadReceipt(pluginDir, entry.Name); receipt != nil {
|
||||||
|
installed = receipt.Version
|
||||||
|
}
|
||||||
|
|
||||||
|
rows = append(rows, []string{entry.Name, entry.Description, installed})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rows) == 0 {
|
||||||
|
if query != "" {
|
||||||
|
cmd.Printf("No plugins matching %q found in catalog\n", query)
|
||||||
|
} else {
|
||||||
|
cmd.Println("No plugins found in catalog")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return printers.TablePrinter(header).Print(cmd.OutOrStdout(), rows)
|
||||||
|
}
|
||||||
48
cmd/flux/plugin_uninstall.go
Normal file
48
cmd/flux/plugin_uninstall.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2026 The Flux authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/fluxcd/flux2/v2/internal/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var pluginUninstallCmd = &cobra.Command{
|
||||||
|
Use: "uninstall <name>",
|
||||||
|
Aliases: []string{"delete"},
|
||||||
|
Short: "Uninstall a plugin",
|
||||||
|
Long: `The plugin uninstall command removes a plugin binary and its receipt from the plugin directory.`,
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
RunE: pluginUninstallCmdRun,
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
pluginCmd.AddCommand(pluginUninstallCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pluginUninstallCmdRun(cmd *cobra.Command, args []string) error {
|
||||||
|
name := args[0]
|
||||||
|
pluginDir := pluginHandler.PluginDir()
|
||||||
|
|
||||||
|
if err := plugin.Uninstall(pluginDir, name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Successf("uninstalled %s", name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
102
cmd/flux/plugin_update.go
Normal file
102
cmd/flux/plugin_update.go
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2026 The Flux authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/fluxcd/flux2/v2/internal/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var pluginUpdateCmd = &cobra.Command{
|
||||||
|
Use: "update [name]",
|
||||||
|
Aliases: []string{"upgrade"},
|
||||||
|
Short: "Update installed plugins",
|
||||||
|
Long: `The plugin update command updates installed plugins to their latest versions.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
# Update a single plugin
|
||||||
|
flux plugin update operator
|
||||||
|
|
||||||
|
# Update all installed plugins
|
||||||
|
flux plugin update`,
|
||||||
|
Args: cobra.MaximumNArgs(1),
|
||||||
|
RunE: pluginUpdateCmdRun,
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
pluginCmd.AddCommand(pluginUpdateCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pluginUpdateCmdRun(cmd *cobra.Command, args []string) error {
|
||||||
|
catalogClient := newCatalogClient()
|
||||||
|
|
||||||
|
plugins := pluginHandler.Discover(builtinCommandNames())
|
||||||
|
if len(plugins) == 0 {
|
||||||
|
cmd.Println("No plugins found")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a specific plugin is requested, filter to just that one.
|
||||||
|
if len(args) == 1 {
|
||||||
|
name := args[0]
|
||||||
|
var found bool
|
||||||
|
for _, p := range plugins {
|
||||||
|
if p.Name == name {
|
||||||
|
plugins = []plugin.Plugin{p}
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return fmt.Errorf("plugin %q is not installed", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginDir := pluginHandler.EnsurePluginDir()
|
||||||
|
installer := plugin.NewInstaller()
|
||||||
|
for _, p := range plugins {
|
||||||
|
result := plugin.CheckUpdate(pluginDir, p.Name, catalogClient, runtime.GOOS, runtime.GOARCH)
|
||||||
|
if result.Err != nil {
|
||||||
|
logger.Failuref("error checking %s: %v", p.Name, result.Err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if result.Skipped {
|
||||||
|
if result.SkipReason == plugin.SkipReasonManual {
|
||||||
|
logger.Warningf("skipping %s (%s)", p.Name, result.SkipReason)
|
||||||
|
} else {
|
||||||
|
logger.Successf("%s already up to date (v%s)", p.Name, result.FromVersion)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
sp := newPluginSpinner(fmt.Sprintf("updating %s v%s → v%s", p.Name, result.FromVersion, result.ToVersion))
|
||||||
|
sp.Start()
|
||||||
|
if err := installer.Install(pluginDir, result.Manifest, result.Version, result.Platform); err != nil {
|
||||||
|
sp.Stop()
|
||||||
|
logger.Failuref("error updating %s: %v", p.Name, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sp.Stop()
|
||||||
|
logger.Successf("updated %s v%s → v%s", p.Name, result.FromVersion, result.ToVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user