command: support local paths for plugins remove

The packer plugins remove command allows users to delete plugins
installed locally.

Previous versions of the command only allowed for the plugins to be
removed using the source for a plugin, and the versions to remove,
optionally.

This commit adds the capability for the plugins to be removed using
their local path, in addition to the regular source+version method, that
way we are able to pipe the results of `packer plugins installed' into
the plugins remove command for quick plugin removal.
pull/12895/head
Lucas Bajolet 2 years ago committed by Lucas Bajolet
parent e6c6520714
commit 930b6c3e2b

@ -7,12 +7,16 @@ import (
"context"
"crypto/sha256"
"fmt"
"log"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/hashicorp/go-version"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/packer/hcl2template/addrs"
"github.com/hashicorp/packer/packer"
plugingetter "github.com/hashicorp/packer/packer/plugin-getter"
"github.com/mitchellh/cli"
)
@ -29,11 +33,19 @@ func (c *PluginsRemoveCommand) Help() string {
helpText := `
Usage: packer plugins remove <plugin> [<version constraint>]
This command will remove all Packer plugins matching the version constraint
for the current OS and architecture.
When the version is omitted all installed versions will be removed.
This command will remove one or more installed Packer plugins.
Ex: packer plugins remove github.com/hashicorp/happycloud v1.2.3
To remove a plugin matching a version contraint for the current OS and architecture.
packer plugins remove github.com/hashicorp/happycloud v1.2.3
To remove all versions of a plugin for the current OS and architecture omit the version constraint.
packer plugins remove github.com/hashicorp/happycloud
To remove a single plugin binary from the Packer plugin directory specify the absolute path to an installed binary. This syntax does not allow for version matching.
packer plugins remove ~/.config/plugins/github.com/hashicorp/happycloud/packer-plugin-happycloud_v1.0.0_x5.0_linux_amd64
`
return strings.TrimSpace(helpText)
@ -46,11 +58,75 @@ func (c *PluginsRemoveCommand) Run(args []string) int {
return c.RunContext(ctx, args)
}
// deletePluginBinary removes a local plugin binary, and its related checksum file.
func deletePluginBinary(pluginPath string) error {
if err := os.Remove(pluginPath); err != nil {
return err
}
shasumFile := fmt.Sprintf("%s_SHA256SUM", pluginPath)
if _, err := os.Stat(shasumFile); err != nil {
log.Printf("[INFO] No SHA256SUM file to remove for the plugin, ignoring.")
return nil
}
return os.Remove(shasumFile)
}
func (c *PluginsRemoveCommand) RunContext(buildCtx context.Context, args []string) int {
if len(args) < 1 || len(args) > 2 {
return cli.RunResultHelp
}
pluginDir, err := packer.PluginFolder()
if err != nil {
return writeDiags(c.Ui, nil, hcl.Diagnostics{
&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Failed to get the plugin directory",
Detail: fmt.Sprintf(
"The directory in which plugins are installed could not be fetched from the environment. This is likely a Packer bug. Error: %s",
err),
},
})
}
if filepath.IsAbs(args[0]) {
if len(args) != 1 {
c.Ui.Error("Unsupported: no version constraint may be specified with a local plugin path.\n")
return cli.RunResultHelp
}
if !strings.Contains(args[0], pluginDir) {
return writeDiags(c.Ui, nil, hcl.Diagnostics{
&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid plugin location",
Detail: fmt.Sprintf(
"The path %q is not under the plugin directory inferred by Packer (%s) and will not be removed.",
args[0],
pluginDir),
},
})
}
log.Printf("will delete plugin located at %q", args[0])
err := deletePluginBinary(args[0])
if err != nil {
return writeDiags(c.Ui, nil, hcl.Diagnostics{
&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Failed to delete plugin",
Detail: fmt.Sprintf("The plugin %q failed to be deleted with the following error: %q", args[0], err),
},
})
}
c.Ui.Say(args[0])
return 0
}
opts := plugingetter.ListInstallationsOptions{
PluginDirectory: c.Meta.CoreConfig.Components.PluginConfig.PluginDirectory,
BinaryInstallationOptions: plugingetter.BinaryInstallationOptions{
@ -92,14 +168,10 @@ func (c *PluginsRemoveCommand) RunContext(buildCtx context.Context, args []strin
return 1
}
for _, installation := range installations {
if err := os.Remove(installation.BinaryPath); err != nil {
c.Ui.Error(err.Error())
return 1
}
shasumFile := fmt.Sprintf("%s_SHA256SUM", installation.BinaryPath)
if err := os.Remove(shasumFile); err != nil {
c.Ui.Error(fmt.Sprintf("failed to remove %s: %s", shasumFile, err))
c.Ui.Error("You may need to remove it manually")
err := deletePluginBinary(installation.BinaryPath)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to remove plugin %q: %q", installation.BinaryPath, err))
continue
}
c.Ui.Message(installation.BinaryPath)
}

Loading…
Cancel
Save