-
Notifications
You must be signed in to change notification settings - Fork 1
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
Fix dependency handling #179
base: t0yv0/dependencies-baseline
Are you sure you want to change the base?
Conversation
@@ -62,6 +66,11 @@ func TestUnmarhsalPropertiesThreadThroughRegisterResource(t *testing.T) { | |||
Element: resource.NewStringProperty(""), | |||
}), | |||
}, | |||
inputsReceived: resource.PropertyMap{ | |||
"foo": resource.NewOutputProperty(resource.Output{ |
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.
Unknowns get normalized to Outputs. That's interesting.
@@ -70,15 +79,20 @@ func TestUnmarhsalPropertiesThreadThroughRegisterResource(t *testing.T) { | |||
Element: resource.NewStringProperty("SECRET"), | |||
}), | |||
}, | |||
inputsReceived: resource.PropertyMap{ |
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.
Secrets get normalized to outputs as well.
}, | ||
{ | ||
name: "array", | ||
inputs: resource.PropertyMap{ | ||
"foo": resource.NewArrayProperty([]resource.PropertyValue{ | ||
resource.NewStringProperty("foo"), | ||
resource.NewSecretProperty(&resource.Secret{ |
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.
Just simplify this since secrets get normalized to outputs, avoid them.
@@ -87,9 +101,74 @@ func TestUnmarhsalPropertiesThreadThroughRegisterResource(t *testing.T) { | |||
inputs: resource.PropertyMap{ | |||
"foo": resource.NewObjectProperty(resource.PropertyMap{ | |||
"p1": resource.NewStringProperty("foo"), | |||
"p2": resource.NewSecretProperty(&resource.Secret{ | |||
Element: resource.NewStringProperty("SECRET"), |
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.
Ditto.
This change is part of the following stack: Change managed by git-spice. |
@justinvp somehow can't tag you as reviewer, strange GH features. |
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've verified that this indeed fixes #234.
Do we have confidence that turning Unknowns and Secrets into OutputProperty is safe?
Those are semantically equivalent. Also, secretes + unknowns should be under test in this repo AFAIK, though maybe something somewhere is lacking in rigor. |
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.
Really appreciate the comments here, thank you for letting me nit pick them.
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.
LGTM. Seems worth merging as-is.
To answer some of your questions...
Does the code need to process ConstructRequest.{Dependencies, PropertyDependencies} or it is obsoleted by first-class Output values?
Just a note that "PropertyDependencies" is actually called inputDependencies
on ConstructRequest
, which I assume is what you mean. Yes, it is obsoleted by first-class Output values. Since you're handling that now, you can ignore ConstructRequest.InputDependencies
.
Dependencies
represents the ResourceOptions.DependsOn
. You will want to handle it. You have this code:
pulumi-terraform-module/pkg/modprovider/server.go
Lines 361 to 365 in ab31764
return pulumiprovider.Construct(ctx, req, s.hostClient.EngineConn(), func( | |
ctx *pulumi.Context, typ, name string, | |
_ pulumiprovider.ConstructInputs, | |
_ pulumi.ResourceOption, | |
) (*pulumiprovider.ConstructResult, error) { |
The ResourceOption
being passed into the callback (currently ignored) will have the DependsOn
filled in for you based on the ConstructRequest.Dependencies, via https://github.com/pulumi/pulumi/blob/6bb0e44f1bb9119435d9ec02217f5ebba9c4b9f3/sdk/go/pulumi/provider.go#L117-L119
You're going to want to think about passing that ResourceOption to your NewModuleComponentResource
inside Construct
, so the actual component gets the resource options that the user specified. I think it's a matter of passing it as the last arg of NewModuleComponentResource
.
if Pulumi resources depend on any of the module's outputs, they now also will depend on all the dependencies of the module's inputs
Do we need to copy up the URN of ModuleState resource and add it to the broadcast of module outputs, so that resources that consume the outputs of the Component resource not only depend on the Component and indirectly on ModuleState because it is the child of the Component, but also directly depend on the ModuleState?
It may be sufficient to only have the module's outputs depend on ModuleState, if ModuleState depends on all the inputs. Then you might not have to propagate all the input dependencies to the module outputs.
Test non-deterministic re-orders the deps sigh. I'll fix up.
|
This change fixes dependency handling. The fix is coarse-grained but important for correctly ordering deletes. The implementation is currently lacking capabilities to track dependencies precisely through the TF black box.
What this does:
if dependencies are passed as inputs to a module instance, ModuleState Custom Resource now depends on all these dependencies. This means, in particular, that
tofu destroy
will now have to complete before the dependencies start getting destroyed themselves. This fixes issues such as Dependency information lost for RDS module depending on AWS resources #234if Pulumi resources depend on any of the module's outputs, they now also will depend on all the dependencies of the module's inputs, they should order their destroy operations accordingly. They also depend on the Component resource itself, and I believe depending on a Component is equivalent in Pulumi to depending on all its children, which should mean they transitively depend on ModuleState as well.
How this works: unfortunately plumbing is not very friendly at the moment for preserving first-class Output values and they tend to get lost. The fixes remedy that just enough to grab these Output values in key locations. Then the code harvests all dependencies from first-class Output values and re-applies them to every output returned from Construct to broadcast them. A test is added that asserts on Pulumi statefile shapes to verify these dependencies.
Fixes #151
Fixes #234
Questions:
ConstructRequest.{Dependencies, PropertyDependencies}
or it is obsoleted by first-class Output values?