Previously the PlanGlue methods all took PlanningOracle pointers as one
of their arguments, which is annoying since all of them should end up with
pointers to the same object and it makes it hard for the PlanGlue
implementation to do any work outside of and between the PlanGlue method
calls.
Instead then we'll have DrivePlanning take a function for building a
PlanGlue implementation given a PlanningOracle pointer, and then the
planning engine returns an implementation that binds a planContext to a
PlanningOracle it can then use to do all of its work.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This is a sketch of starting and configuring provider instances once they
are needed and then closing them once they are no longer needed. The
stubby implementation of data resource instance planning is there mainly
just to illustrate how this is intended to work, but it's not yet complete
enough to actually function.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
The eval system gradually reports the "desired" declarations at various
different levels of granularity, and so the planning engine should compare
that with the instances in the previous run state to notice when any
existing resource instance is no longer in the desired state.
This doesn't yet include a real implementation of planning the deletion of
such resource instances. Real planning behaviors depend on us having some
sort of provider instance and ephemeral resource instance manager to be
able to make requests to configured providers, so that will follow in
subsequent commits before we can implement the actual planning behaviors.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
In a new async recursive tree walk we'll gradually traverse the tree of
module calls and announce the desired state objects at each level, so that
the PlanGlue implementation can then compare that with its own record of
the prior state to determine by omission which resource instances are
"orphans" that should be planned for deletion.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This puts the infrastructure in place to allow us to notify the PlanGlue
implementation about what's declared in the configuration so it can detect
orphaned resource instances by omission, but stops short of actually doing
that because it'll require another concurrent recursive tree walk which
is likely to be complex enough to deserve to live in its own later commit.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Previously this had the idea that the planning engine would work in two
subphases where first it would deal with the desired state (decided by
evaluating the configuration) and then it would do a second pass to plan
to delete any resource instances that didn't show up in the desired state.
Although that would technically work, we need to keep configured provider
instances open for the whole timespan between planning the first
desired resource instance and the final orphan instance using each
provider, and so splitting into two phases effectively means we'd have
provider instances sitting open but idle waiting for the desired state
subphase to complete to learn if they are needed for the orphan subphase.
This commit stubs out (but does not yet implement) a new approach where
the orphan planning can happen concurrently with the desired state
planning. This works by having the evaluator gradually describe to the
planning engine which module calls, module call instances, resources, and
resource instances _are_ present in the desired state -- as soon as that
information becomes available -- so that the planning engine can notice
by omission what subset of the prior state resource instances are no longer
desired and are therefore orphans.
This means that the planning engine should now have all of the information
it needs to recognize when a provider can be closed: the PlanningOracle
reports which _desired_ resource instances (or placeholders thereof) are
expected to need each provider instance, and the prior state tracks
exactly which provider instance each prior resource instance was associated
with, and so a provider's work is finished once all instances in the union
of those two sets have had their action planned.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Continuing to split up some of the source files that have grown long over
ongoing experimentation, this is the start of splitting the config_plan.go
file into smaller parts.
For now only PlanningOracle gets its own file, but other types related to
planning might follow in later commits.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This was the big known missing piece for making a "real" implementation
of planning using this new package, so that the planning engine can know
what configuration to use when preparing a configured provider instance
for planning requests.
I'm sure there are other missing pieces that I've just not learned about
yet, but this is still a good checkpoint to stop iterating on lang/eval
for a little while and start stubbing out the planning engine.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This is a little too busy/complicated for my liking but it's a place to
start and hopefully we'll be able to cut this down a little after we see
how the planning engine implementation turns out.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This is my current idea for how to resolve the chicken/egg problem of the
planning phase needing to know who uses ephemeral resource instances and
provider instances but us needing to evaluate the configuration to know
those relationships.
This borrows the evaluation behavior previously used for
ConfigInstance.Validate to produce a conservative evaluation of the
configuration without depending on any configured providers or ephemeral
resource instances, which we (in future commits) will use to discover
the relationships between those objects so that the real walk during the
planning phase can know when to start and stop them.
This relies on the idea that an evaluation with values stubbed out as
unknown should produce _at least_ the relationships that would occur with
fewer unknown values, though it might also report additional dependencies
that would vanish once values become more known. This gives the plan phase
something to start with and then we'll learn a tighter set of dependencies
during the planning phase which will form the basis of the apply-time
execution graph.
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>