Go 1.17 and earlier used a different syntax for build constraint comments,
starting with "+build". Go 1.18 changed this to the modern "go:build" form
as part of standardizing the structure of toolchain directive comments,
and so for a while it was convention to include comments in both styles
to allow building with both old and new Go compilers.
However, Go 1.17 is no longer supported, and regardless of that we only
expect OpenTofu to be built with the specific version we have selected
in "go.mod" and ".go-version" anyway, so we no longer need the legacy form
of these comments: the all supported Go toolchains now support the new
form, which this commit retains.
golangci-lint v2.6.0 includes a check for this legacy form, so removing
this will also allow us to upgrade to a newer version of that linter
aggregator in a future commit.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
The JSON object describing an input variable can now include two additional
properties:
- "type" provides a JSON representation of the variable's type constraint,
if one is set. Omitted if either there is no constraint declared at all
or if it's set to "any", which are equivalent and both mean that the
type is completely unconstrained.
This uses the standard cty representation of a type constraint, which
matches how OpenTofu already describes types in the provider protocol,
in state snapshots, and in saved plan files.
- "required" directly represents whether callers are required to provide
a value for the variable. This is technically redundant since it is
set to true unless "default" is also set, but this avoids the need for
consuming software to reimplement this rule and potentially allows us to
make this rule more complicated/subtle in future if needed.
For some reason the documentation about the JSON configuration
representation did not previously mention the "variables" property at all,
so this adds documentation for both the new properties and the pre-existing
properties.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
We previously added the -config mode for showing the entire assembled
configuration tree, including the content of any descendent modules, but
that mode requires first running "tofu init" to install all of the
provider and module dependencies of the configuration.
This new -module=DIR mode returns a subset of the same JSON representation
for only a single module that can be generated without first installing
any dependencies, making this mode more appropriate for situations like
generating documentation for a single module when importing it into the
OpenTofu Registry. The registry generation process does not want to endure
the overhead of installing other providers and modules when all it actually
needs is metadata about the top-level declarations in the module.
To minimize the risk to the already-working full-config JSON representation
while still reusing most of its code, the implementation details of package
jsonconfig are a little awkward here. Since this code changes relatively
infrequently and is implementing an external interface subject to
compatibility constraints, and since this new behavior is relatively
marginal and intended primarily for our own OpenTofu Registry purposes,
this is a pragmatic tradeoff that is hopefully compensated for well enough
by the code comments that aim to explain what's going on for the benefit
of future maintainers. If we _do_ find ourselves making substantial changes
to this code at a later date then we can consider a more significant
restructure of the code at that point; the weird stuff is intentionally
encapsulated inside package jsonconfig so it can change later without
changing any callers.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This extends statemgr.Persistent, statemgr.Locker and remote.Client to
all expect context.Context parameters, and then updates all of the existing
implementations of those interfaces to support them.
All of the calls to statemgr.Persistent and statemgr.Locker methods outside
of tests are consistently context.TODO() for now, because the caller
landscape of these interfaces has some complications:
1. statemgr.Locker is also used by the clistate package for its state
implementation that was derived from statemgr.Filesystem's predecessor,
even though what clistate manages is not actually "state" in the sense
of package statemgr. The callers of that are not yet ready to provide
real contexts.
In a future commit we'll either need to plumb context through to all of
the clistate callers, or continue the effort to separate statemgr from
clistate by introducing a clistate-specific "locker" API for it
to use instead.
2. We call statemgr.Persistent and statemgr.Locker methods in situations
where the active context might have already been cancelled, and so we'll
need to make sure to ignore cancellation when calling those.
This is mainly limited to PersistState and Unlock, since both need to
be able to complete after a cancellation, but there are various
codepaths that perform a Lock, Refresh, Persist, Unlock sequence and so
it isn't yet clear where is the best place to enforce the invariant that
Persist and Unlock must not be called with a cancelable context. We'll
deal with that more in subsequent commits.
Within the various state manager and remote client implementations the
contexts _are_ wired together as best as possible with how these subsystems
are already laid out, and so once we deal with the problems above and make
callers provide suitable contexts they should be able to reach all of the
leaf API clients that might want to generate OpenTelemetry traces.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
The code for matching relevant_attributes against resource_drift entries
(a part of the heuristic for deciding whether to show "changes outside of
OpenTofu" in the human-oriented plan UI) was previously assuming that paths
in resource_drift would always be valid for the associated resource
instance object values because in most cases the language runtime will
detect invalid references and so fail to generate a plan at all.
However, when the reference is to something within a dynamically-typed
argument (such as the manifest in kubernetes_manifest) and when it appears
only as an argument to either the "try" or "can" functions (so the dynamic
error is intentionally suppressed) the language runtime can't catch it
and so the incorrect reference will leak out into relevant_attributes,
thereby violating assumptions made by the path matcher.
Instead then, we'll continue the existing precedent that this "relevant
attributes" mechanism is a best-effort heuristic that prefers to succeed
with an incomplete result rather than to fail, extending that to the
traversals in the plan renderer which will now treat incorrectly-typed
steps as not matching rather than causing OpenTofu to crash completely.
Since a reference to something that doesn't exist cannot succeed it also
cannot possibly _actually_ contribute directly to the final result of the
expression it appeared in, so in practice it should be okay to disregard
these invalid references for the purposes of deciding which changes outside
of OpenTofu seem likely to have caused the actions that OpenTofu is
proposing to make during the apply phase.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
We previously had two tests of how the module installer responds to
cancellation (e.g. SIGINT) which were flakey because they tried to rely
on the cancellation being detected at some arbitrary point before the
module installer attempted to make a request, which isn't guaranteed in
practice because our interrupt mechanism only aims to cause OpenTofu to
exit "soon", with no guarantee about how much ongoing progress it will
make before it does.
To make these tests more robust, we'll now instead tell the module
installer to install from a real HTTP server that is intentionally designed
to stall the client by accepting its request but then just leaving the
connection open without responding.
This means that we can now test the more realistic situation of the cancel
signal being triggered after a slow request is already in progress, and
be sure that we're definitely sending the cancel signal at a moment that
matches that intention.
This is similar to a strategy we previously took to improve the reliability
of the tests for cancellation of the _provider_ installer, in
TestInit_cancelProviders. However, our provider installer version of this
used an intentionally-stalling implementation of getproviders.Source
instead of running a real server because the provider installer is designed
to support configurable installation methods, while the module installer
is not: its policy about what module source types are accepted is
hard-coded in package getproviders, at least for now.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
The "backendConfigNeedsMigration" helper evaluates the backend
configuration inline to compare it with the object previously saved in the
.terraform/terraform.tfstate file.
However, this wasn't updated to use the new "static eval" functionality
and so was treating any references to variables or function calls as
invalid, causing a spurious "backend configuration changed" error when
re-initializing the working directory with identical backend configuration
settings.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>