-
Notifications
You must be signed in to change notification settings - Fork 9.6k
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
ephemeral resource grpc wrappers #35784
Conversation
5d06b1a
to
6cb1309
Compare
cde52e1
to
6cb1309
Compare
Add deferrals to the protocol. The renew and close calls had an extra state field which was unneeded.
6cb1309
to
6f5007e
Compare
The graph building around nodeEphemeralResourceClose was not correct, and allowed the provider to be shut down before the ephemeral resource was closed. The nodeEphemeralResourceClose is not connected to the main provider node because it's not added until after the providers are all connected. Because the close node needs to wait on all dependencies of the ephemeral resource, the usual graph building process no longer works. There have been a lot of improvements since the original provider close transformer was introduced, so we should be able to refactor that in terms of what consumes the provider rather than just looking for edges from the provider node.
The apply process for ephemeral resources was not accounted for, and the nodeExpandApplyableResource (which isn't really an expansion node!?) isn't going to be able to expand into the ephemeral nodes. For the time being we can inject the apply node during expansion to get the ephemeral resources started.
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.
drive-by comment 🚗: RenewEphemeralResource.Request
and CloseEphemeralResource.Request
still have state
in this proto file
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.
thanks, I seemed to have somehow rebased that back in 😵
DynamicValue result = 3; | ||
optional bytes private = 4; | ||
Deferred deferred = 5; |
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.
I will match the provider side with the new field/naming once this gets merged 👍🏻
For the removal of is_closable
, is the plan for Close
to be called for all ephemeral resources regardless of if they were renewed/not renewed?
Additionally, will returned diagnostics from Close
stop execution or will they behave more like the Stop
RPC for providers and just log?
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.
Yeah, Close would always be called. Making Close
a defined part of the lifecycle regardless of whether it does anything or not makes the implementations much simpler, and since the plugin has to implement the calls anyway, it would have to at least be a noop regardless of whether it's called.
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.
Oh yeah, and diagnostics from Close
would only be able to pass on some info to the user, and make Terraform exit with an error. The Close
has to happen after all dependencies have used the value, so if there were an error there are no more operations to stop execution of.
@@ -301,6 +301,9 @@ func (n *nodeExpandPlannableResource) knownModuleSubgraph(ctx EvalContext, addr | |||
DynamicTransformer(func(graph *Graph) error { | |||
// We'll add nodes for any orphaned resources. | |||
rs := state.Resource(addr) | |||
if rs == nil { |
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, I ran into this one as well. I went for skipping this transformer on ephemeral nodes since it was a bit less confusing to the reader, but this is ok with me as well.
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.
yeah, I figured you would have hit this too, for now it was the minimal change to run the tests ;)
Reminder for the merging maintainer: if this is a user-visible change, please update the changelog on the appropriate release branch. |
I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active contributions. |
This represents a basic working implementation for ephemeral resources in Terraform, along with the preliminary PRs:
resources/ephemeral
package for tracking ephemeral resource lifecycle #35742(excerpts from original description in the proof-of-concept PR #35078 authored by @apparentlymart)
Ephemeral Resources
Terraform currently has two "resource modes": managed resources (
resource
blocks) describe objects that Terraform is directly managing, while data resources (data
blocks) describe objects that are managed elsewhere that the current configuration depends on. But in both cases the assumption is that those objects persist in some sense from plan to apply and from one plan/apply round to the next, and that Terraform is supposed to detect and react to any changes to those objects and therefore needs to persist information about them itself.Ephemeral resources, (
ephemeral
blocks) on the other hand, represent objects that -- at least, as far as Terraform is concerned -- exist only briefly during a single Terraform phase, and then get cleaned up once the phase is complete.The general idea of ephemeral resources, then, is that their lifecycle includes three events:
OpenEphemeral
: Prepares the object for use. For some kinds of objects this would represent a "create" action, but for others it might just open a temporary session to something that already exists, such as in the SSH tunnel use-case.This operation is the one that establishes the result attributes that can be accessed from other parts of the module where the resource is declared. All of these results would be ephemeral values, so that they can vary from plan to apply. For example, opening an SSH tunnel is likely to cause a different local TCP port number to be allocated each time, and so consistency between plan and apply phases is not expected.
RenewEphemeral
: Some ephemeral remote objects need to be periodically refreshed in order to stay "live", such as leases for Vault secrets.This optional operation is therefore opted into by the provider's
OpenEphemeral
response, by providing a private set of data that should be sent back to the provider'sRenewEphemeral
implementation and a deadline before which Terraform must renew it. The provider can then do whatever is needed to keep the object from expiring, and optionally return another renew request with a new deadline in order to repeat this renewal process.CloseEphemeral
: Once Terraform has completed work for all objects that refer to the ephemeral resource, this operation gives the provider an explicit signal that the object is not longer required so that it can be promptly destroyed or invalidated.This detail is particularly helpful for the Vault provider and fixes a limitation I ran into immediately back in 2016: a dynamic secret fetched using a
data
block can never have its lease explicitly terminated, because data resources were intended only to read information about an object someone else is managing, not to directly manage an object (a Vault lease).While the implementation has changed somewhat, this still borrows heavily from #35078. There's still a lot more work to do, but as of now the the basic functionality is there, and this PR allows other parallel work to commence.