Skip to content

Commit

Permalink
terraform: Close provider after ephemeral resources closed
Browse files Browse the repository at this point in the history
Because ephemeralResourceCloseTransformer runs very late in the transform
sequence, it's too late to get provider open and close nodes associated
with it automatically.

We don't actually need to worry about the provider _open_ dependency
because our close node always depends on all of our open nodes and they
will in turn depend on the provider open they need. But for close we need
to delay closing the provider until all of the associated ephemeral
resources have been closed, so we need to do a little fixup:

If any of particular ephemeral resource's open nodes have provider close
nodes depending on them, those provider close nodes should also depend
on the ephemeral resource close node. That then describes that the
provider should remain open for as long as at least one ephemeral resource
instance owned by that provider remains live, which makes it okay for us
to do our periodic background renew requests and our final close requests.
  • Loading branch information
apparentlymart committed May 6, 2024
1 parent 432571e commit e6c8430
Showing 1 changed file with 38 additions and 0 deletions.
38 changes: 38 additions & 0 deletions internal/terraform/transform_ephemeral_resource_close.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,44 @@ func (t *ephemeralResourceCloseTransformer) Transform(g *Graph) error {
}
}

// Because this graph transformer runs very late in the sequence, we'll
// also need to do some work to make sure the close node is associated
// with the same provider as the open nodes; the open nodes get that
// dealt with by earlier transformers, and we can't benefit directly from
// that here but we can at least make use of the results of that earlier
// work.
//
// The idea here is that each open node should have a graphNodeCloseProvider
// depending on it, and we're going to just connect them all up to
// also depend on the corresponding ephemeral value close node, assuming
// that the earlier provider-close wiring knew what it was doing and so we
// don't need to sweat the details too much in here.
for _, elem := range closeNodes.Elems {
configAddr := elem.Key
closeNode := elem.Value
for _, openNode := range openNodes.Get(configAddr).Elems() {
for _, dependent := range g.UpEdges(openNode).List() {
// FIXME: Ugh... testing for a concrete node type rather than
// an interface isn't great here. But as long as ephemeral
// values is just a prototype it's not desirable to go on
// a big refactoring spree, so we'll just live with it.
//
// If you're here considering how to turn this prototype into
// shippable code, _please_ do something about this because
// tight coupling with specific concrete node types has
// historically been a maintenence hazard.
if v, ok := dependent.(*graphNodeCloseProvider); ok {
// any "close provider" node that depends on any of our
// opens should also depend on our close, because if
// a provider needs to be running to open then it needs
// to be running to close too.
log.Printf("[TRACE] ephemeralResourceCloseTransformer: %s must run after %s", dag.VertexName(v), dag.VertexName(closeNode))
g.Connect(dag.BasicEdge(v, closeNode))
}
}
}
}

// Finally, if we found any ephemeral resources that don't have any
// consumers then we'll prune out all of their open and close nodes
// to avoid redundantly opening and closing something that we aren't
Expand Down

0 comments on commit e6c8430

Please sign in to comment.