-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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: add --path flag to packer plugins install #12643
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 1 Ignored Deployment
|
054aa21
to
4cc8747
Compare
4cc8747
to
666039c
Compare
d1d4d45
to
acf3ef9
Compare
0abc8c0
to
7f43b65
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the approach and understand why the logic for FlagSet is specified within the install command.
command/plugins_install.go
Outdated
}}) | ||
} | ||
|
||
binaryPath := fmt.Sprintf( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For windows binaries we will need the .exe extension as well.
command/plugins_install.go
Outdated
@@ -128,3 +198,167 @@ func (c *PluginsInstallCommand) RunContext(buildCtx context.Context, args []stri | |||
|
|||
return 0 | |||
} | |||
|
|||
func (c *PluginsInstallCommand) InstallFromBinary(args *PluginsInstallArgs) int { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you are doing here. Is there a way to reuse the Checksummer for obtaining and write the checksum file, the InFolders, and BinaryInstallOptions for generating file names.
I have to think through this a little but would there be any benefit to adding this as a method on plugingetter.Requirement
?
You can write the code to be something like the following and reuse a bit of the logic from InstallLatest along with the call to describe you have in InstallFromBinary.
// a plugin requirement that matches them all
pluginRequirement := plugingetter.Requirement{
Identifier: plugin,
}
if args.Version != "" {
constraints, err := version.NewConstraint(args.Version)
if err != nil {
c.Ui.Error(err.Error())
return 1
}
pluginRequirement.VersionConstraints = constraints
}
if runtime.GOOS == "windows" && opts.Ext == "" {
opts.BinaryInstallationOptions.Ext = ".exe"
}
var newInstall *plugingetter.Installation
var err error
// If we did specify a binary to install the plugin from, we ignore
// the Github-based getter in favour of installing it directly.
if args.PluginPath != "" {
newInstall, err := pluignRequirement.InstallLocalBinary(args.PluginPath, plugingetter.InstallOptions{
InFolders: opts.FromFolders,
BinaryInstallationOptions: opts.BinaryInstallationOptions,
Force: args.Force, //This may not be needed.
})
} else {
getters := []plugingetter.Getter{
&github.Getter{
UserAgent: "packer-getter-github-" + pkrversion.String(),
},
}
newInstall, err := pluginRequirement.InstallLatest(plugingetter.InstallOptions{
InFolders: opts.FromFolders,
BinaryInstallationOptions: opts.BinaryInstallationOptions,
Getters: getters,
Force: args.Force,
})
}
....
This new flag allows the `packer plugins install' command to install a plugin from a local binary rather than from Github. This command will only call `describe' on the plugin, and won't do any further checks for functionality. The SHA256SUM will be directly computed from the binary, so as with anything manual and potentially sourced by the community, extra care should be applied when invoking this.
The --force option for packer init and packer plugins install enforces installation of a plugin, even if it is already locally installed. This will become useful if for some reason a pre-existing plugin binary/version is already installed, and we want to overwrite it.
To avoid plugins being installed with a specific version when a path is used for installing a plugin from a locally sourced plugin binary, we explicitly reject the combination of both a path and a version for plugins install.
When installing a plugin with packer plugins install --path, we only accept release versions of a plugin, as otherwise the loading can be inconsistent if for example a user specifies a required_plugins block in their template, in which case the plugins will be ignored. Until we have a simpler loading scheme then, we will reject non-release versions of plugins to avoid confusion.
7f43b65
to
688c689
Compare
688c689
to
91f2461
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great. Glad we were able to refactor for consistency I left a few suggestions to consolidate code a bit more and tighten up the scope of a few variables.
command/plugins_install.go
Outdated
} | ||
|
||
func (c *PluginsInstallCommand) RunContext(buildCtx context.Context, args []string) int { | ||
func (pa *PluginsInstallArgs) AddFlagSets(flags *flag.FlagSet) { | ||
flags.StringVar(&pa.PluginPath, "path", "", "install the plugin from a specific path") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
flags.StringVar(&pa.PluginPath, "path", "", "install the plugin from a specific path") | |
flags.StringVar(&pa.PluginPath, "path", "", "install the binary specified by path as a Packer plugin.") |
command/plugins_install.go
Outdated
func (c *PluginsInstallCommand) RunContext(buildCtx context.Context, args []string) int { | ||
func (pa *PluginsInstallArgs) AddFlagSets(flags *flag.FlagSet) { | ||
flags.StringVar(&pa.PluginPath, "path", "", "install the plugin from a specific path") | ||
flags.BoolVar(&pa.Force, "force", false, "force installation of a plugin, even if already installed") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
flags.BoolVar(&pa.Force, "force", false, "force installation of a plugin, even if already installed") | |
flags.BoolVar(&pa.Force, "force", false, "force installation of the specified plugin, even if already installed.") |
command/plugins_install.go
Outdated
} | ||
|
||
if pa.Path != "" && pa.Version != "" { | ||
c.Ui.Error("Invalid arguments: a version cannot be specified with --path") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
c.Ui.Error("Invalid arguments: a version cannot be specified with --path") | |
c.Ui.Error("Invalid arguments: a version cannot be specified when using --path to install a local plugin binary") |
command/plugins_install.go
Outdated
} | ||
|
||
pa.PluginName = args[0] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
command/plugins_install.go
Outdated
@@ -68,30 +133,36 @@ func (c *PluginsInstallCommand) RunContext(buildCtx context.Context, args []stri | |||
}, | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
command/plugins_install.go
Outdated
return writeDiags(c.Ui, nil, hcl.Diagnostics{&hcl.Diagnostic{ | ||
Severity: hcl.DiagError, | ||
Summary: "Unable to find plugin to promote", | ||
Detail: fmt.Sprintf("The plugin %q failed to be opened because of an error: %s", args.PluginName, err), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Detail: fmt.Sprintf("The plugin %q failed to be opened because of an error: %s", args.PluginName, err), | |
Detail: fmt.Sprintf("The plugin %q failed to be opened because of an error: %s", pluginIdentifier, err), |
Detail: fmt.Sprintf("Failed to read plugin binary from %q: %s", args.PluginPath, err), | ||
}}) | ||
} | ||
_ = pluginBinary.Close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should handle this error in case close fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eh, the chances of Close
failing are excessively thin, and will be closed anyway when the process terminates, so we probably can overlook this one (we would too if we deferred)
outputPrefix+opts.BinaryInstallationOptions.FilenameSuffix(), | ||
) | ||
|
||
outputPlugin, err := os.OpenFile(binaryPath, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0755) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the same permissions we use inside of InstallLatest?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe so? If not we should probably settle for 755 for both, since read/execute makes sense for eveyone else, and all perms for the owner
command/plugins_install.go
Outdated
pluginContents := &bytes.Buffer{} | ||
_, err = io.Copy(pluginContents, pluginBinary) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: We only need the pointer for copying.
pluginContents := &bytes.Buffer{} | |
_, err = io.Copy(pluginContents, pluginBinary) | |
pluginContents := bytes.Buffer{} | |
_, err = io.Copy(&pluginContents, pluginBinary) |
return writeDiags(c.Ui, nil, hcl.Diagnostics{&hcl.Diagnostic{ | ||
Severity: hcl.DiagError, | ||
Summary: "Invalid version", | ||
Detail: fmt.Sprintf("Packer can only install plugin releases with this command (ex: 1.0.0), the binary's reported version is %q", desc.Version), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't solve the problem for folks using dev builds right.
Detail: fmt.Sprintf("Packer can only install plugin releases with this command (ex: 1.0.0), the binary's reported version is %q", desc.Version), | |
Detail: fmt.Sprintf("Installation of prerelease binaries with this command is not allowed, the binary's reported version is %q", desc.Version), |
~> packer plugins install --path ~/.packer.d/plugins/packer-plugin-amazon github.com/hashicorp/happycloud
Error: Invalid version
Packer can only install plugin releases with this command (ex: 1.0.0), the
binary's reported version is "1.2.9-dev"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not indeed for now, it's one of the things we need to address/fix for 1.11.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something seems off
~> tree ~/.packer.d/plugins/github.com/hashicorp/
/Users/dev/.packer.d/plugins/github.com/hashicorp/
├── amazon
│ ├── packer-plugin-amazon_v1.2.8_x5.0_darwin_arm64
│ └── packer-plugin-amazon_v1.2.8_x5.0_darwin_arm64_SHA256SUM
└── happycloud
├── packer-plugin-happycloud_v1.2.8_x5.0_darwin_arm64
└── packer-plugin-happycloud_v1.2.8_x5.0_darwin_arm64_SHA256SUM
2 directories, 4 files
~> packer plugins installed
/Users/dev/.packer.d/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.8_x5.0_darwin_arm64
91f2461
to
6f36012
Compare
Read original binary into memory to fix case when installation destination and source were the same, resulting in an empty binary.
6f36012
to
62d7afd
Compare
62d7afd
to
af2a439
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice updates ✅
I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. |
This new flag allows the
packer plugins install
command to install a plugin from a local binary rather than from Github.This command will only call
describe
on the plugin, and won't do any further checks for functionality. The SHA256SUM will be directly computed from the binary, so as with anything manual and potentially sourced by the community, extra care should be applied when invoking this.NOTE: marking as draft as it is not yet meant to be merged into main, or released soon. This is experimental and we'll decide what to do with it later.