-
Notifications
You must be signed in to change notification settings - Fork 9.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Module Expansion Activate! #24461
Module Expansion Activate! #24461
Conversation
As the Graph is walked, the current way to set the context path was to have the walker return a context from EnterPath. This required that every node know it's absolute path, which can no longer be the case during plan when modules have not been expanded. This introduces a new method called WithPath, which returns a copy of the context with the internal path updated to reflect the method argument. Any use of the EvalContext that requires knowing the path will now panic if it wasn't explicitly set to ensure that evaluations always occur in the correct path. Add EvalContext to the GraphWalker interface. EvalContext returns an EvalContext that has not yet set a path. This will allow us to enforce that all context operations requiring a module instance path will require that a path be explicitly set rather than evaluating within the wrong path.
While the Expander itself now handles the recursive expansion of modules, Resources themselves still need to be expanded twice, because the evaluation of the Resource, which entails evaluating the for_each or count expressions, is separate from the ResourceInstance expansion. Add a nodeExpandPlannableResource to do handle this expansion to allow all NodePlannableResources to call EvalWriteResourceState with an absolute address.
Resources also need to be expanded during apply, which cannot be done via EvalTree due to the lack of EvalContext.
Use the new addrs type here. Also remove the uniqueMap from the config transformer. We enforce uniqueness during config loading, and this is more likely to have false positives due to stringification than anything.
We can't get module instances during transformation, so we need to reduce the Dependencies to using `addrs.ConfigResource` for now.
Remove the shims where they aren't necessary from the Init and Close provider nodes. This also removed some provider path checks from the builtin eval context, which cannot be resolved since the context may not be created with a ModuleInstance path.
The expand logic was separated into nodeExpandRefreshableManagedResource, but the orphan logic wasn't updated.
simplify the test a bit and add a few more combinations to the config
eval nodes no longer always have a context path
5e9b2fb
to
4f1692c
Compare
case forEachMap != nil: | ||
expander.SetResourceForEach(n.Addr.Module, n.Addr.Resource, forEachMap) | ||
default: | ||
expander.SetResourceSingle(n.Addr.Module, n.Addr.Resource) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: what is the expected behavior when SetResourceSingle
is called when count = 0
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah! I found the answer in a comment just below this (and was misreading the actual condition, still on my first ☕️):
// -1 signals "count not set"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup, count = 0
is still in list-mode, just with 0 instances.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks reasonable to me, though I suggest you get a second review with someone with more context :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly 🎉 and a comment about where comment might be improved/more understanding left for Future Readers
|
||
m := testModule(t, "plan-modules-count") | ||
func TestContext2Plan_moduleExpand(t *testing.T) { | ||
// Test a smattering of plan expansion behavior |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
smattering!
if countDiags.HasErrors() { | ||
return nil, countDiags.Err() | ||
} | ||
// nodeExpandModule itself does not have visibility into how its ancestors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
helpful comment!
// NewNodeAbstractResource creates an abstract resource graph node for | ||
// the given absolute resource address. | ||
func NewNodeAbstractResource(addr addrs.AbsResource) *NodeAbstractResource { | ||
// FIXME: this should probably accept a ConfigResource |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And now it does!
terraform/node_resource_apply.go
Outdated
// nodeExpandApplyableResource handles the first layer of resource | ||
// expansion during apply. This is required because EvalTree does not have a | ||
// context with which to expand the resource into multiple instances. | ||
// This type should be a drop in replacement for NodeApplyableResource, and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a "drop-in replacement" is the implication that it is used instead of NodeApplyableResource
in certain scenarios, but not all? And what are those scenarios? (something that might be helpful to clarify here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah good point, I do that too often in comments. I've already done the replacement, and the comment should only explain the "why"
@@ -100,12 +100,7 @@ func (n *NodeApplyableResourceInstance) References() []*addrs.Reference { | |||
|
|||
// GraphNodeAttachDependencies | |||
func (n *NodeApplyableResourceInstance) AttachDependencies(deps []addrs.ConfigResource) { | |||
var shimmed []addrs.AbsResource | |||
for _, r := range deps { | |||
shimmed = append(shimmed, r.Absolute(r.Module.UnkeyedInstanceShim())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice
This name method won't be called in the full graph, and remove it to prevent confusion with the parent node in logs.
Waiting on this bad boy, in need of |
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further. |
This turns on module expansion in the config, with most basic functionality working. A major exception is that while providers cannot be configured within an expanded module, there is no validation for that yet and the results are going to be undefined.
There are some
UnkeyedInstanceShim
calls are left in the abstract provider, because providers need to be evaluated before expansion happens. This is OK, since we will pre-validate that providers cannot be configured within expanding modules. There is also a call in resource validation, because we need to create a context within which we can validate, but there is no expansion to create module instances. This type of usage of theUnkeyedInstanceShim
will likely remain for the time being.To link the bulk of the work together here, the series of PRs directly leading to this is #24154, #24296, #24331, #24346, #24362, #24389, #24444, #24454.
Other key points in this PR:
Add
EvalContext.WithPath
As the Graph is walked, the current way to set the context path was to
have the walker return a context from EnterPath. This required that
every node know it's absolute path, which can no longer be the case
when modules have not been expanded.
This introduces a new method called WithPath, which returns a copy of
the context with the internal path updated to reflect the method
argument. Any use of the EvalContext that requires knowing the path will
now panic if it wasn't explicitly set to ensure that evaluations always occur
in the correct path. While this may be beneficial for development, this
should be converted to a contextual error later on, so in the rare event that
we evaluate an unknown path the user can report the error in a useful way.
Add
EvalContext
to theGraphWalker
interface.EvalContext returns an EvalContext that has not yet set a path. This
will allow us to enforce that all context operations requiring a module
instance path will require that a path be explicitly set rather than
evaluating within the wrong path.
Add separate expand nodes to all Resource nodes that will need expansion.
While the Expander itself now handles the recursive expansion of
modules, Resources still need to be expanded twice, because
the evaluation of the Resource, which entails evaluating the
for_each
orcount
expressions, is separate from theResourceInstance
expansion.Adding expander nodes ensures that the individual eval nodes can be
created with the correct path for evaluation.
Track dependencies via
addr.ConfigResource
We don't have access to module instances during the full graph transformations,
so we can't record these in the state. Using
addrs.ConfigResource
won't changethe current behavior, but makes the dependencies tracking less precise when
instances are connected to resources in other modules. We may likely revisit
this once we can ensure Refresh no longer needs to evaluate Resource
configuration.
Implements #17519, but leaving open until we are more feature complete.