Provider and Provisioner Managers encapsulate all of
the logic nessesary to start, manage, and stop plugins.
They also have the advantage of sharing a schema cache between
managers started in different parts of the application.
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
This mostly mechanical change defines a central location
for providing installed plugins as a cohesive unit to the
rest of the application. This also provides a location
for future caching of schemas and other potential optimizations.
This is part of the overall initiative to start stripping
functionality out of the tofu package into re-usable components
which can be used by the new engine.
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
We have some test code that includes *addrs.Target values in fmt calls with
the %s and %q verbs, but that type was not actually a fmt.Stringer before.
Go 1.26 is introducing some new checks that cause those uses to cause
failures when building those tests. We could potentially change the tests
to produce the string representation in a different way, but we typically
expect our address types to be "stringable" in this way, so instead we'll
just make Target be a fmt.Stringer, delegating to the String method of
the underlying addrs.Targetable implementation. The addrs.Targetable
interface requires a String method, so all implementations are guaranteed
to support this.
Note that we're not actually using Go 1.26 yet at the time of this commit,
but this is an early fix to make the upgrade easier later. I verified this
using go1.26rc1.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This removes most of the code previously added in 491969d29d, because we
since learned that the hashicorp/helm provider signals deferral when any
unknown values are present in provider configuration even though in
practice it can sometimes successfully plan changes in spite of those
unknown values.
That therefore made the hashicorp/helm provider behavior worse under this
change than it was before, returning an error when no error was actually
warranted.
The ephemeral resources implementation landed later and was also
interacting with this change, and so this isn't a line-for-line revert of
the original change but still removes everything that was added in support
of handling provider deferral signals so that we'll be able to start fresh
with this later if we find a better way to handle it.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This is a _very_ early, minimal plumbing of the execution graph builder
into the experimental planning engine.
The goal here is mainly just to prove the idea that the planning engine can
build execution graphs using the execgraph.Builder API we currently have.
This implementation is not complete yet, and also we are expecting to
rework the structure of the planning engine later on anyway so this initial
work focuses on just plumbing it in to what we had as straightforwardly
as possible.
This is enough to get a serialized form of _an_ execution graph included
in the generated plan, though since we don't have the apply engine
implemented we don't actually use it for anything yet.
In subsequent commits we'll continue building out the graph-building logic
and then arrange for the apply phase to unmarshal the saved execution graph
and attempt to execute it, so we can hopefully see a minimal version of all
of this working end-to-end for the first time. But for now, this was mainly
just a proof-of-concept of building an execution graph and capturing it
into its temporary home in the plans.Plan model.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
During the "walking skeleton" phase of our work on the new planning engine
we're intentionally changing other subsystems like the CLI layer as little
as possible and just wiring things together as straightforwardly as
possible so we can find gaps in our new architectural model before we get
too invested in the current experimental shape of it.
With that in mind, this slightly extends the plans.Plan type and its
associated protobuf serialization so that we'll be able to get an opaque
representation of the new runtime's "execution graph" concept from plan
to apply while the CLI layer is still using the traditional plan models.
This is probably not how we'll deal with this in the long run, but it's
intended to be something we can tear back out relatively easily if we
decide either to abandon this "execution graph" idea altogether or once
we reach the point of implementing a new plan model that better suits the
new architecture.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This was previously dealing okay with the case where a resource doesn't
have the requested instance, but was not handling the situation where the
resource doesn't exist at all yet.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Most of what we interact with in configgraph is other parts of the
evaluator that automatically get memoized by patterns like OnceValuer, but
the value for a resource instance is always provided by something outside
of the evaluator that won't typically be able to use those mechanisms, and
so the evaluator's ResourceInstance.Value implementation will now provide
memoization on behalf of that external component, to ensure that we end
up with only one value for each resource instance regardless of how that
external component behaves.
In the case of the current planning phase, in particular this means that
we'll now only try to plan each resource instance once, whereas before
we would ask it to make a separate plan for each call to Value.
For now this is just retrofitted in an minimally-invasive way as part of
our "walking skeleton" phase where we're just trying to wire the existing
parts together end-to-end and then decide at the end whether we want to
refactor things more. If this need for general-purpose memoization ends
up appearing in other places too then maybe we'll choose to structure this
a little differently.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
ResultRef[*states.ResourceInstanceObjectFull] is our current canonical
representation of the "final result" of applying changes to a resource
instance, and so it is going to appear a bunch in the plan and apply
engines.
The generic type is clunky to read and write though, so for this one in
particular we'll offer a more concise type alias that we can use for parts
of the API that are representing results from applying.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This registry client code is very, very old and in particular predates the
creation of the separate "registry-address" library and OpenTofu's own
"package addrs", so it had its own type for representing module addresses.
It also had some historical confusion about the difference between a module
package and a module, which meant the code was pretty unclear about whether
it was dealing in module packages or module source addresses: in practice
we were always leaving the "Submodule" field empty because the registry
client isn't the component responsible for dealing with modules in package
subdirectories, but this made the code confusing to read and maintain.
This change therefore removes the legacy package regsrc altogether and
adopts regaddr.ModulePackage as the canonical representation of registry
module package addresses. This therefore makes the module registry client
agree with the module installer about what vocabulary types we're using,
and so we no longer need shim code for converting between the two
representations.
To make it abundantly clear that the registry client deals only in package
addresses, the client methods and arguments are renamed to reflect that,
and the callers updated to match.
While in the area anyway I also adjusted a few others things that were not
aligned with our modern conventions, but tried to keep it limited to
relatively localized changes for ease of review. There's probably room for
more improvement here in subsequent commits.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This is just a minimal set of changes to introduce uses of the new
states.ResourceInstanceObjectFull to all of the leaf functions related to
planning managed and data resource instances.
The main goal here was just to prove that we'd reasonably be able to look
up objects with the new type in all of the places we'd need to. We're
planning some more substantial changes to the planning engine in future
commits (e.g. to generate execution graphs instead of traditional plans)
and so we'll plumb this in better as part of that work.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Previously we had a gap here where we only knew the resource type to use
when there was a "desired state" object to get it from, which isn't true
when we're planning to destroy an undesired object.
The new extended model for resource instance object state gives us direct
access to the resource type name, so we can now handle that properly.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Instead of states.ResourceInstanceObject, we'll now use the "full"
representation added in a recent commit. This new representation is a
better fit for execgraph because it tracks all of the relevant information
about a resource instance object inline without assuming that the object
is always used in conjunction with a pointer to the entire state.
We're not really making any special use of those new capabilities yet. This
is mostly just mechanical updates to refer to the new type, and to fill
in values for the extra fields as far as that's possible without doing
further refactoring.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Our existing state model is designed with the assumption that anyone who
is accessing a ResourceInstanceObjectSrc will be doing so from an object
representing the entire state at once, and so they can separately fetch
information about the resource as a whole and the provider instance it
belongs to if needed.
In our new language runtime we want to be able to just pass around pointers
to individual resource instance object states rather than the entire state
data structure, and so these two new "full" variants extend the object
representation with a provider instance address and the name of the
resource type within that provider.
This also adopts a slightly different representation of the value itself,
making use of some newer Go language features, so that we don't need quite
so much duplication between the "source" and decoded versions of this
model. In practice it's only the Value field that needs to vary between
the two, because that's the part where we require provider schema
information to decode.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
TestAccLookupModuleVersions was previously testing for a property in the
registry's JSON response that is not part of the documented "modules.v1"
protocol.
Presumably this was covering some extension property in our predecessor's
public registry implementation, which therefore made this test pass in its
original form interacting with that specific registry implementation.
However, OpenTofu does not depend on this extension property in any way
outside of this test, so there's no benefit to testing for this behavior
in OpenTofu. Regardless, the OpenTofu Registry doesn't implement this
extension so this test cannot pass in its current form running against that
implementation of the registry protocol.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Earlier work in opentofu/opentofu#2661 caused the module installer to
treat the registry client and the package fetcher as optional dependencies
so that local-only tests (by far our common case across the whole codebase)
could avoid instantiating the registry and go-getter client code and risk
accidentally depending on network services.
However, at the time I didn't notice that this package had TF_ACC=1
acceptance tests, and so although I made systematic updates across all the
tests which appeared to make them pass there were actually several that
were being skipped and so I didn't notice that I hadn't updated them well
enough.
This gets them all passing again by giving the ones that intentionally
access the real OpenTofu Registry and some test-only GitHub repositories
the clients they need to do that.
In a future commit I intend to add this package to our end-to-end test
job that runs as part of our pull request checks so that we're less likely
to forget to update these tests under future maintenance.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
To support the workflow of saving a plan to disk and applying it on some
other machine we need to be able to represent the execution graph as a byte
stream and then reload it later to produce an equivalent execution graph.
This is an initial implementation of that, based on the way the execgraph
package currently represents execution graphs. We may change that
representation more in future as we get more experience working in the new
architecture, but this is intended as part of our "walking skeleton" phase
where we try to get the new architecture working end-to-end with simple
configurations as soon as possible to help verify that we're even on the
right track with this new approach, and try to find unknown unknowns that
we ought to deal with before we get too deep into this.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This is some minimal glue to help the new runtime use the providers that
were gathered up by the existing logic in the "command" package.
This is cheating a little because this is relying on "tofu init" still
using the old approach just enough to find out which providers are needed
and get them installed, but our current focus is on the main plan and
apply phases and so it's convenient to be able to leave that part untouched
for now and return to improve it later, once we have more of the
fundamentals in place.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This is a relatively uninteresting milestone where it's possible to load
and plan a root module that contains nothing except local values and
output values.
The module loader currently supports only local sources and the plugin
APIs just immediately return errors, so configurations more complicated
than that are likely to just fail immediately with one or more errors.
We'll gradually improve on this in later commits.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
None of these actually work yet, but this satisfies the new-style config
loader enough for it to return a real error instead of immediately
panicking.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
We currently re-export evalglue.ExternalModules, but the method in that
interface requires returning evalglue.UncompiledModule and so we need to
export that too or else it's impossible to actually implement the interface
from outside this family of packages.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This doesn't actually work yet. It's just to sketch out a minimal overall
sequence of steps to make this behave somewhat like the main implementation
of "tofu plan", and then we'll make it work better in subsequent commits.
The main omission as of this commit is that we don't yet pass module,
provider, and provisioner dependency access objects in the EvalContext,
and so config loading immediately fails trying to request the root module
from a nil object.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>