Skip to content
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

Merged
merged 10 commits into from
Oct 1, 2024
Merged

Conversation

jbardin
Copy link
Member

@jbardin jbardin commented Sep 26, 2024

This represents a basic working implementation for ephemeral resources in Terraform, along with the preliminary PRs:


(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's RenewEphemeral 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.

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.
@jbardin jbardin marked this pull request as ready for review September 30, 2024 21:42
@jbardin jbardin requested a review from a team September 30, 2024 21:42
Copy link
Member

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

Copy link
Member Author

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 😵

Comment on lines +637 to +639
DynamicValue result = 3;
optional bytes private = 4;
Deferred deferred = 5;
Copy link
Member

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?

Copy link
Member Author

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.

Copy link
Member Author

@jbardin jbardin Oct 1, 2024

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 {
Copy link
Collaborator

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.

Copy link
Member Author

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 ;)

@jbardin jbardin merged commit 7170a80 into main Oct 1, 2024
6 checks passed
@jbardin jbardin deleted the jbardin/ephemeral-grpc-wrappers branch October 1, 2024 18:56
Copy link
Contributor

github-actions bot commented Oct 1, 2024

Reminder for the merging maintainer: if this is a user-visible change, please update the changelog on the appropriate release branch.

Copy link
Contributor

github-actions bot commented Nov 1, 2024

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.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 1, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants