Open jjo93sa opened 10 months ago
Hi @jjo93sa,
Since you're using required_plugins
you won't be able to use the plugin located alongside the packer
executable, instead, that method of loading only considers what's in the configuration's plugin directory. It can take several forms depending on the environment, I encourage you to take a look at our docs for more information.
Here's some links that may be useful to understand the problem:
Also, if you want to manually install a plugin to your plugin directory, with Packer v1.10.0 (released yesterday), we added a --path
flag to the packer plugins install
command, which installs a binary to the plugin directory with the right name/hierarchy as packer expects for required_plugins
.
For your case, that'd be something like packer plugins install --path "/usr/local/bin/packer-plugin-openstack" "github.com/hashicorp/openstack"
, which will automatically install the plugin in the right place.
As for packer plugins installed
, it only reports plugins that are installed through packer init
or packer plugins install
, i.e. those that match the convention documented in plugin loading workflow.
Hope that helps!
@lbajolet-hashicorp Thanks for your reply. So, if I understand correctly, one method of including plugins, i.e. the resource
block:
required_plugins {
ansible = {
source = "github.com/hashicorp/ansible"
version = "~> 1"
}
}
}
... excludes the use of "local" plugins, for example those next to the Packer binary? Even if the two methods load two different plugins? I couldn't see anything about that in the documents?
Is there anyway to install a manually built plugin in the plugins directory, such that both can be mentioned in the required_plugins
directory?
I experimented this morning by removing the required_plugins
block, and downloading the stock (v1.1.1) OpenStack and Anisble plugins, placing them in /usr/bin/local
and indeed that seems to work OK. Great: progress!
However, if I do the following:
git clone https://github.com/hashicorp/packer-plugin-openstack.git
git checkout tags/v1.1.1
go build
I see the same error as I first reported:
023/12/07 09:56:25 [INFO] Packer version: 1.9.4 [go1.20.7 linux amd64]
2023/12/07 09:56:25 [TRACE] discovering plugins in /usr/local/bin
2023/12/07 09:56:25 [INFO] Discovered potential plugin: ansible = /usr/local/bin/packer-plugin-ansible_v1.1.1_x5.0_linux_amd64
2023/12/07 09:56:25 [INFO] Discovered potential plugin: openstack = /usr/local/bin/packer-plugin-openstack_v1.1.1_x5.0_linux_amd64
2023/12/07 09:56:25 found external [-packer-default-plugin-name- local] provisioner from ansible plugin
Error loading configuration:
fork/exec /usr/local/bin/packer-plugin-openstack_v1.1.1_x5.0_linux_amd64: no such file or directory
So the only thing I can conclude is that I'm doing something wrong in the build of the OpenStack plugin, and the configuration error results from that rather than the placement of the plugin? The plugin documents only mention go build
and no other commands or dependencies.
As an aside, I think there is a typo in the Manual Installation guide
For example, if your configuration directory is located in ~/.config/packer, you can copy the binary to ~/.config/plugins/packer-plugin-NAME, and Packer will be able to load it afterwards.
Shouldn't that read: ~/.config/packer/plugins/packer-plugin-NAME
?
@lbajolet-hashicorp Thanks for your reply. So, if I understand correctly, one method of including plugins, i.e. the
resource
block:required_plugins { ansible = { source = "github.com/hashicorp/ansible" version = "~> 1" } } }
... excludes the use of "local" plugins, for example those next to the Packer binary? Even if the two methods load two different plugins? I couldn't see anything about that in the documents?
Your understanding is correct. The plugin information described within the required _plugins block provides additional metadata to Packer for loading a specific plugin. Metadata that is provided through the plugin directory structure and filename. Local plugins that sit along side the executable do not provide this information and are ignored when a template contains a required_plugins block.
The use of required_plugins with Packer's historical plugin loading has been a pain point we are working to resolve. We attempted to capture the gotcha of required_plugins and local binaries here. Do you have suggestions on how we can make it clearer?
I see the same error as I first reported:
023/12/07 09:56:25 [INFO] Packer version: 1.9.4 [go1.20.7 linux amd64] 2023/12/07 09:56:25 [TRACE] discovering plugins in /usr/local/bin 2023/12/07 09:56:25 [INFO] Discovered potential plugin: ansible = /usr/local/bin/packer-plugin-ansible_v1.1.1_x5.0_linux_amd64 2023/12/07 09:56:25 [INFO] Discovered potential plugin: openstack = /usr/local/bin/packer-plugin-openstack_v1.1.1_x5.0_linux_amd64 2023/12/07 09:56:25 found external [-packer-default-plugin-name- local] provisioner from ansible plugin Error loading configuration: fork/exec /usr/local/bin/packer-plugin-openstack_v1.1.1_x5.0_linux_amd64: no such file or directory
So the only thing I can conclude is that I'm doing something wrong in the build of the OpenStack plugin, and the configuration error results from that rather than the placement of the plugin? The plugin documents only mention
go build
and no other commands or dependencies.
I believe there may be an issue with the compiled binary. The error fork/exec ... no such file or directory
is the an error you will can when a binary expects / requires glibc.
Before copying the binary you can validate that it works by running ./packer-plugin-openstack describe
~> ./packer-plugin-openstack describe
{"version":"1.1.1","sdk_version":"0.4.0","api_version":"x5.0","builders":["-packer-default-plugin-name-"],"post_processors":[],"provisioners":[],"datasources":[]}
I see you are running Alpine which wont have glibc I believe you need to use musl libc.
If the describe command fails as I expect it would can you try building with CGO_ENABLED=0.
CGO_ENABLED=0 go build
When we build our binaries for releases we disable cgo on all binaries so that they are statically linked and don't dependent on the system's glibc. I don't have direct experience with building on Alpine if disabling CGO is not the option. Maybe @lbajolet-hashicorp could provide more info if this turns out to be the issue.
Is there anyway to install a manually built plugin in the plugins directory, such that both can be mentioned in the
required_plugins
directory?
In Packer 1.10.0 there packer plugins install
command has been updated to support the installation of locally built binaries so that they work with required_plugins
. Taking your current workflow and using Packer 1.10.0 you can run the following to get things working as expected.
git clone https://github.com/hashicorp/packer-plugin-openstack.git
git checkout tags/v1.1.1
go build
packer plugins install --path ./packer-plugin-openstack github.com/hashicorp/openstack
However, this would install the plugin into the Packer Plugind directory and not /usr/local/bin.
Is there a reason why it needs to be in /usr/local/bin?
@nywilken Thanks for your help:
Looking at the documentation link you provided, I'd say this section was misleading, at least in my mind:
This logic however is ignored when plugins are defined in required_plugins blocks; instead, for every plugin required in this way, Packer will only consider them if they're installed in Packer's plugin directory, under a directory hierarchy that matches the source, with the plugin name respecting a convention.
I think the problem here is the "for every plugin" part. That, again to me, makes it seem that the following part of the sentence only applies to plugins in the required_plugins
block, not all plugins. So, I think something like this would more accurately represent the situation (as I understand it):
Note, however, that it is not possible to mix "local" plugins alongside those defined in a
required_plugins
block; the two mechanisms are mutually exclusive, if arequired_plugins
block exists in a template, no local plugins will be used.
HTH
Some good news:
If the describe command fails as I expect it would can you try building with CGO_ENABLED=0.
CGO_ENABLED=0 go build
This worked! (Alongside removing the required_plugins
block and no longer executing packer init
). Thanks a lot for your help.
I had seen the packer plugins install
command in v1.10.0. Unfortunately, the licence change to BSL in v1.10.0 means we're not permitted to use that version.
Is there a reason why it needs to be in /usr/local/bin?
No, there's no reason why the plugins need to be in that specific location, I can place them anywhere, accepting the limitations of the Packer version we're using.
One use case I have is working on a Packer template that contains required_plugins
, but where I want to use a locally developed/modified plugin.
I can install the development version via packer plugins install --path
, but since it's a pre-release version.InitializePluginVersion("1.2.3", "dev")
results in the plugin being installed as packer-plugin-foo_v1.2.3-dev_x5.0_darwin_arm64
.
Which does not match a Packer template of:
packer {
required_plugins {
foo = {
version = ">= 1.2.0"
source = "github.com/someting/foo"
}
}
}
Right now I'm working around it by either:
required_plugins
in the template while developing1.2.3-dev
during development""
to the prerelease argument of InitializePluginVersion
to avoid adding any suffixNeither of these are great workarounds, so it would be nice if there was an easier way to use development versions with required_plugins
.
version
could take a list of constraints (logically OR
match)? version
could allow HCL variables, so it can be dynamic?packer
that tells it to match prereleases as well?To be clear I want to:
required_plugins
section in my Packer template, checked into version control, so that consumers of the template can do packer init
to get a working setup.Having a pre-release suffix on the installed development version seems good/useful, to be able to distinguish a released version from a pre-release, so ideally the solution is something that doesn't require modifying the Packer template, and doesn't require faking non-pre-releases in the plugin 😅
Hi @torarnv,
Timing is 10/10 on your updating this issue, we've just released v1.11.0-alpha that should address your concerns. Namely you can install -dev
binaries with the packer plugins install --path
command, and it will be loaded by Packer, even with a required_plugins
statement in your template, assuming the following is true:
I believe this should fill-in the blanks for your use-case, please let us know if there's something unclear or unintuitive with this workflow!
Damn @lbajolet-hashicorp , you just keep saving my day! 🤩 This is perfect, will test the alpha and give feedback ❤️
No release version alternative is installed, otherwise it will have precedence
Does this mean that if 0.0.4 is installed and I install 0.0.5-dev, I will not get my dev version? Or does it only apply if I have both 0.0.5 and 0.0.5-dev installed?
That's only if you have 0.0.5-dev and 0.0.5 installed yep; in this case 0.0.5 will mask 0.0.5-dev, so the latter won't be loadable anymore. If you have 0.0.4 and 0.0.5-dev, assuming your constraints allow it, 0.0.5-dev will have precedence over 0.0.4.
If you choose to also, we included a --ignore-prerelease-plugins
flag to circumvent this behaviour and forbid loading -dev
binaries for both the validate
and build
commands.
That sounds like a perfect fit, thanks!
Having played with this new feature a bit, one thing that is a bit unintuitive is the override logic of 0.0.5
being preferred over 0.0.5-dev
.
The typical case is that a plugin is released, and then installed, as version 0.0.5
(git describe
giving v0.0.5
).
Then someone clones the repo of the plugin to fix an issue or add a feature, and want to test the changes before submitting them upstream. Maybe they have a dirty working tree, or maybe they have made a commit. Their local git describe
would be e.g. v0.0.5-1-gb1299dd
, and produce v0.0.5-dev
. Which would not be picked up.
With the current approach, the only way seems to be to preemptively modify the version of the plugin you're working on. Even if you're not the one in charge of releasing 😄 And to make sure that version change doesn't end up in the commit you're submitting upstream.
Do you have any tips to improve this process? Perhaps 0.0.5-dev
should override 0.0.5
? Possibly via a optional flag (--prefer-prerelease-plugins
)?
Once the change has been tested and merged upstream, the maintainer of the plugin releases them as e.g. 0.0.6
(git describe
giving v0.0.6
), at which point it would of course make sense to override v0.0.5-dev
.
Thanks!
I was thinking I could work around this by turning git describe --tags --long --dirty
v0.0.5-1-gb1299dd
into a version number v0.0.5.1-gb1299dd
, but of course that doesn't work for v0.0.5-0-gb1299dd-dirty
, where you've made some changes locally on top of a released version, but haven't committed them yet.
Would be nice to be able to test the plugin in this scenario by installing it (into possibly a custom PACKER_PLUGIN_PATH
).
Ignoring the corner case of v0.0.5-0-gb1299dd-dirty
this still doesn't seem to be a viable workaround right now:
❯ make && ./packer-plugin-ipsw describe
go build -ldflags="-X 'main.GitDescribe=v0.0.12-3-g9724548'" -o packer-plugin-ipsw
{"version":"0.0.12.3-g9724548","sdk_version":"0.4.0","api_version":"x5.0","builders":[],"post_processors":[],"provisioners":[],"datasources":["-packer-default-plugin-name-"]}
❯ make install
go build -ldflags="-X 'main.GitDescribe=v0.0.12-3-g9724548'" -o packer-plugin-ipsw
packer plugins install --path packer-plugin-ipsw github.com/torarnv/ipsw
Error: Invalid version
Packer can only install plugin releases with this command (ex: 1.0.0) or
development pre-releases (ex: 1.0.0-dev), the binary's reported version is
"0.0.12.3-g9724548"
Could we relax https://github.com/hashicorp/packer/blob/main/command/plugins_install.go#L260 so that it doesn't care what exactly the pre-release format is? The general Packer plugin requirements for versioning doesn't seem to require "dev" based on https://github.com/hashicorp/packer/blob/main/version/version.go#L27
I tried to please Packer by hard-coding the pre-release version to dev
, while still producing 0.0.5.1001
as the version to keep it higher than the 0.0.5
:
https://gist.github.com/torarnv/fbcfd990e84e510a2e5b5a8f285b8b5d#file-stdin-patch-L44
But the Packer plugin version regex only allows major.minor.patch
version:
https://github.com/hashicorp/packer/blob/main/packer/plugin-getter/plugins.go#L103
😅
As we use http://github.com/hashicorp/go-version for the versions, could we perhaps relax this? It seems to allow more than three version components based on https://github.com/hashicorp/go-version/blob/main/version_test.go#L69 ?
Hi @torarnv,
Thanks for the feedback, there's a lot to process so I'll try to respond to each point one-by-one, but forgive me if there's something I don't address in this message, feel free to press some more!
Having played with this new feature a bit, one thing that is a bit unintuitive is the override logic of 0.0.5 being preferred over 0.0.5-dev.
The typical case is that a plugin is released, and then installed, as version 0.0.5 (git describe giving v0.0.5). [...] Perhaps 0.0.5-dev should override 0.0.5 ?
Regarding this one, I can understand your issue, but I don't think we'll change the implementation regarding versioning, our assumption is that version is generally updated in this fashion (I'll take your example to illustrate):
Version = "0.0.5"
is pushed on the repo, and tagged, so it triggers the job that performs the releaseVersion = "0.0.6"
and VersionPrerelease = "dev"
is pushed on main: from now on we're building v0.0.6-dev
each timeBoth actions should happen when the release is made. This is the intended workflow for plugin development, and one approach we use for the plugins we develop internally (ex: https://github.com/hashicorp/packer-plugin-amazon/pull/464, https://github.com/hashicorp/packer-plugin-azure/pull/377, etc.). This is also what the attribute's documentation indicates.
I can understand if this feels kinda weird though, especially if you're used to bumping the version at release, and not beforehand; the workflows are deeply incompatible.
The flag you're suggesting --prefer-prerelease-plugins
could be an idea, though I'm not certain this is where we want to go right now. Our goal with that change is essentially to make the development process uniform so that it becomes easier and more predictable how Packer behaves with respect to plugin discovery and loading, changing this order with extra flags may in my opinion make it a bit confusing in several regards.
For example: one repo may adopt our workflow, others will adopt a similar workflow as yours, so the usage of the flag will need to be documented in that plugin's README for example.
Also, having this as a flag means that if testing/building multiple plugins at the same time, and their versioning conventions are different, this will make it impossible to test without tinkering with either's Version
and re-building.
I'm open to discussing this of course, but for those reasons, I'm enclined to adopt a convention, which could be what you suggested to be clear.
Do you have any tips to improve this process?
My advice would be, if the version.Version
is 0.0.5
in your local tree, you can always change it to 0.0.6
, and this 0.0.6-dev
plugin will now have precedence over 0.0.5
, so it will be loaded in your case.
Alternatively, you can remove the installed v0.0.5
version of the plugin, and install the one you're building instead, this way there won't be any conflict.
I was thinking I could work around this by turning [...] a version number
v0.0.5.1-gb1299dd
Unfortunately in this case the -gb1299dd
part will be incompatible with our version checks, since we restricted pre-releases to only dev
. We opted to go this route in order to have a simple ordering, without having to specify an order that took into account alpha
/beta
/rc
, etc.
I'd love to get your thoughts on that process, is there something that'd prevent you from adopting this workflow?
The general Packer plugin requirements for versioning doesn't seem to require "dev" based on https://github.com/hashicorp/packer/blob/main/version/version.go#L27
Good call, this comment does not represent how this works nowadays it seems. This should be updated in the scaffolding. Though this could change depending on the previous discussion point.
I tried to please Packer by hard-coding the pre-release version to dev, while still producing 0.0.5.1001 as the version to keep it higher than the 0.0.5:
https://gist.github.com/torarnv/fbcfd990e84e510a2e5b5a8f285b8b5d#file-stdin-patch-L44
But the Packer plugin version regex only allows major.minor.patch version
Indeed for now it is how it behaves, we're experimenting on some changes to that workflow however with this PR, be advised though, it is bound to change a bit. I'll let you know when the PR is in a testable state so you can let us know if this improves the experience for you?
Sorry for the wall of text answer here :sweat_smile:, let's continue discussing this and get to a point where we'll all be happy with how Packer behaves :)
PS: regarding those changes and the rationale behind them, we've published a blog post detailing our thought process, please feel free to give it a read, we'd be interested to hear what you think about this.
Thank you very much for the detailed reply @lbajolet-hashicorp 🙌🏻
I can fully appreciate not wanting to change the version matching logic to prefer 0.0.5-dev
over 0.0.5
😃 The motivation for the suggestion was, as you touch upon, that plugins typically bump version on release, to the version released. A workflow as you describe where the bump to the next version happens when releasing the previous would fix that. Perhaps the Packer scaffolding template could include Makefile
and/or goreleaser
magic/best practices to do releases that way, to promote plugins to adopt that flow (if it doesn't already, I might be missing something).
Having thought about the --prefer-prerelease-plugins
some more, I think it's not really that useful or critical after all. If I know I'm working with development version of a plugin I can always make sure I don't have any released version of the same plugin installed. And if I'm in a setting where I can't uninstall existing plugins I can always run with PACKER_PLUGIN_PATH
to create an isolated environment.
The blog post was very informative, thank you for that! I think the choice of dev
as the only pre-release version that Packer accepts can benefit from being highlighted in documentation and elsewhere, as it might help others who, like me, assumed Packer's version parsing/support was generic semver with x.y.z-foo+baz
.
Other than that, ship it! 🎉😅
Community Note
Overview of the Issue
We are unable to make a manually-installed plugin work. Our scenario is that we have a custom version of the OpenStack plugin, which we want to test alongside the stock Ansible plugin specified in the
packer
block:Our custom build of the OpenStack plugin is installed in the same directory (
/usr/local/bin
) as the Packer binary itself. According to the trace, the plugin is "discovered" but then an error is produced that the file just found doesn't exist, a configuration error.What we've tried to fix this:
0777
,0755
root
(to match the Packer binary),ci-pipeline-build
(the user executing Packer)packer-plugin-openstack
,packer-plugin-openstack_v1.1.1_x5.0_linux_amd64
/usr/local/bin
;/home/ci-pipeline-builder/.config/packer/plugins/
;/home/ci-pipeline-builder/.config/packer/plugins/github.com/hashicorp/openstack/
Reproduction Steps
Clone plugin repo:
Build repo:
Copy built binary to directory where Packer binary lives:
Execute Packer build:
Packer version
v1.9.4
Simplified Packer Template
TBC
Operating system and Environment details
Executing in a GitLab runner Docker container
Alpine Linux:
alpine:3.15.4
Log Fragments and crash.log files
Note in the following there's no output from the
packer plugins installed
command, so it seems theinit
must be failing?At that point the runner process fails and cleans up.