Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

command: support local paths for plugins remove #12886

Merged
merged 1 commit into from
Mar 15, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 84 additions & 12 deletions command/plugins_remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand All @@ -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)
Expand All @@ -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{
Expand Down Expand Up @@ -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)
}
Expand Down
Loading