When remotely installing a plugin, constraints are used by Packer to
determine which version of a plugin to install.
These constraints can be arbitrarily complex, including operators and
ranges in which to look for valid versions.
However, the versions specified in those constraints should always be
final releases, and not a pre-release since we don't explicitly support
remotely installing pre-releases.
This commit therefore addds checks to make sure these are reported ASAP,
even before the source is contacted to list releases and picking one to
install.
Compared to Terraform, Packer was lacking a capability to encode/decode
strings to/from base64-encoded text encoded with another encoding.
This could be problematic in some cases, mainly when working with
Windows, as most of the OS uses UTF-16LE as its standard encoding for
many operations.
Therefore, we take a page from Terraform here, and add those functions
to what Packer supports in an HCL2 context.
The ParsePluginSource function can be invoked from either a HCL2 context
(when parsing a required_plugins block), or from the command-line
itself.
While in the first context a hcl.Diagnostics is coherent, in case the
source to parse is a command-line argument, for example when installing
or removing a plugin, the error message cannot have an HCL context,
leading to errors that are incorrectly prefixed by a <nil> string dure
to the lack of a reference to attach the diagnostic to.
Therefore, in order to fix this behaviour, the logic that parses plugin
sources now returns an error, and attaching the error to an HCL subject
is done independently, if needed.
When specifying/installing plugins, a source URI is required for Packer
to be able to locate or install a plugin to the local plugin hierarchy.
The plugin hierarchy is based on the plugin source, where each component
in this hierarchy will become a directory.
In order to avoid sources with too many levels of nesting, causing a lot
of mkdirs, we limit the number of sources to 16 in this commit, this
should be long enough for most of our users.
When running a packer command on an HCL2 template, depending on whether
or not there are required_plugin blocks defined, Packer may need to
discover and register a plugin's components multiple times.
This is the behaviour ever since those blocks were introduced to Packer,
but given we are doing the operation multiple times, this is suboptimal.
This commit changes the way things works by first doing the restricted
discovery of plugins (as dictated by required_plugins), then proceeding
to the global discovery, with the change that subsequent component
discoveries will not have precedence over those pre-discovered anymore.
This allows us to invert the call order of both discovery phases safely,
and maintains the constraints described in the templates.
The source parsing logic was heavily directed towards Github compatible
source URIs, however if we want to support more cases, we need to make
sure we are able to specify those URIs, and to load plugins installed
from those sources.
Right now, since the getters available are only github.com, we will not
support remotely instlling plugins from sources other than github.com,
with the same set of constraints as before. However, we do support now
installing from a local plugin binary to any kind of source, and we
support loading them, including if a template wants this plugin
installed locally with version constraints.
The invalid_inexplicit_source_2 subtest for parse used to fail in
previous versions of Packer, but with the latest changes to plugin
source management, it won't, at least at parsing time, instead it fails
later when the Github getter (the only available for now) cannot get the
plugin binary from the source, as the source is not a valid Github URI.
Since we have both version/version.go and version/VERSION to specify
version strings, both are a bit redundant.
As version/VERSION is supposed to be the source of truth now, we are
using it to derive the version informaiton we used to rely on in Packer
and its subcommands.
Note: doing this prevents us from changing the version/prerelease
through ldflags though as we derive Version/VersionPrerelease from the
rawVersion variable.
The fmt command reformats HCL2 templates, provided it can parse the file
and reformat its contents according to the standards set by the HCL
library's formatters.
However, if the file is malformed for some reason, the command will fail
with a parse error, but while the parse error message is shown, the
actual errors in the template(s) are not forwarded, making it hard for
users to understand what went wrong with the contents of the file
they're trying to format.
In order to be more helpful with those errors, we now forward those
parsing errors to the UI.
Since we now support loading pre-releases, we also want Packer to be
able to ignore them by user demand, so we put in place the
infrastructure to modulate this.
When Packer is loaded, we used to perform plugin discovery.
This was done for every call to Packer, including when it is executed as
a plugin, arguably against what the comments document.
Doing this as early in the loading process makes it harder to change
this behaviour, as we'd need to introduce flags aside from the rest, and
handle them manually, which is not optimal.
Therefore, we change this: now when Packer starts executing, it will not
attempt to discover installed plugins anymore, and instead will only try
to load them when a configuration has been parsed, and is being used to
perform actions (typically build/validate).
When Packer orders the plugins by their version, we'd assumed it was
ordered from highest to lowest.
However, this was the case because our implementation of `Less' was
actually returning `>=', which is not what it was supposed to do.
This commit therefore fixes the implementation of `Less' to do what it
is documented to do, and ensures the behaviour is correct through
additional testing.
Changing this requires some changes to the loading process as well
because of the aforementioned assumption with regards to ordering.
Right now we had two paths for discovering installed plugins, i.e.
through plugin-getter's `ListInstallations' function, or through the
`Discover' call, which relied on a glob to list the installations.
This was required since we allowed plugins to be installed in multiple
locations, and with different constraints.
Now that we force a certain convention, we can consolidate the logic
into ListInstallations, and rely on that logic in `Discover' to load a
plugin into the PluginConfig for the current Packer run.
Since we'll only look in the plugin directory, and not from multiple
sources now, for installing/listing plugins, we can simplify the
structures which used to accept multiple directories so they only accept
one.
Since we're removing the alternative plugin installation directories in
favour of only supporting installing them in the PACKER_PLUGIN_PATH
directory, we only return one directory when getting the known plugin
directories.
Not validating the bucket's name during parse leads to configurations
being marked as valid, even if the bucket name is not, which will fail
during a real build afterwards.
To avoid this problem and fail with an error as quickly as possible, we
add a check during parsing, so that it gets reported for validate as
well.
cty's new "refinements" concept allows us to reduce the range of unknown
values from our functions. This initial changeset focuses only on
declaring which functions are guaranteed to return a non-null result,
which is a helpful baseline refinement because it allows "== null" and
"!= null" tests to produce known results even when the given value is
otherwise unknown.
This commit also includes some updates to test results that are now
refined based on cty's own built-in refinement behaviors, just as a
result of us having updated cty in the previous commit.
If a variable is defined and overriden in the packer command-line, but
there's a problem during the evaluation of this override (type error
typically), we show an error message which details the problem.
This message points to a temporary in-memory HCL2 "file" that we use for
parsing and evaluating the expression for the variable, but since it's
virtual, there's no point in using this as the source for the error, as
it will always yield "line 0" and no contents.
So, in order to limit confusion here, we remove the source for this
error message.
When a user invokes packer for a build or validation, the template being
processed needs components to be present for Packer to process it
without error.
If the component cannot be found from the plugins loaded (or from the
components bundled with Packer), Packer errors, and the command fails.
This is expected, but the error message does not suggest anything to fix
the error, potantially leaving users confused at the problem.
This commit suggests either a replacement (in case of a typo), or points
to the web documentation for Packer, specifically the integrations, so
they can look for the plugin they're missing, and install it, so
subsequent invocations of Packer work.
The previous implementation of the GetVarsByType function worked only on
top-level attributes, ignoring the nested blocks in the structure.
This implies that if a datasource depends on another through an
expression within a nested block, we may not execute it first, and then
executing this datasource before its dependent is possible, resulting in
an error in the end.
This commit is an attempt at making this more reliable for HCL configs,
but only works on configs lifted from HCL files for now. We need to make
this more reliable for later iterations.