-
Notifications
You must be signed in to change notification settings - Fork 17
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
Refactor Custom Resources to allow configuring timeouts and secrets #1795
Conversation
Previously it was assumed that the custom resources do not concern themselves with secretness or handle timeouts. But this is necessary to support CloudFormation based Custom Resources. Those can contain secret outputs and support configuring timeouts. This change modifies the `CustomResource` interface to accomomdate those requirements. In detail this means that the Create/Update/Read lifecycle methods now returns a `PropertyMap` instead of a generic `map[string]interface{}` and take a timeout parameter.
Does the PR have any schema changes?Looking good! No breaking changes found. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1795 +/- ##
==========================================
+ Coverage 41.17% 45.36% +4.18%
==========================================
Files 35 38 +3
Lines 5775 5879 +104
==========================================
+ Hits 2378 2667 +289
+ Misses 3187 2989 -198
- Partials 210 223 +13 ☔ View full report in Codecov by Sentry. |
The test coverage of the touched files is mostly through integration tests. I'll try to add some more tests to cover parts of this with units 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.
Does this change have any user facing impact, or is it purely internal?
This is purely internal |
var createErr error | ||
var payload map[string]interface{} | ||
timeout := time.Duration(req.GetTimeout()) * time.Second |
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.
Unlike bridged providers, guessing there is no need to merge with schema-derived timeouts here?
Also, double-checking, this will be 0
if req.GetTimeout() is unset?
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.
No, there's no notion of passing timeouts to the CloudControl based resources (yet).
At the current time no resource is using timeouts yet. This is just prep for the next changes related to CFN CustomResources
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 yes, this will be 0
if no timeouts were specified
// checkpointObject puts inputs in the `__inputs` field of the state. | ||
func checkpointObject(inputs resource.PropertyMap, outputs map[string]interface{}) resource.PropertyMap { | ||
object := resource.NewPropertyMapFromMap(outputs) | ||
object["__inputs"] = resource.MakeSecret(resource.NewObjectProperty(inputs)) |
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 was a fairly interesting quirk.
"github.com/pulumi/pulumi/sdk/v3/go/common/resource" | ||
) | ||
|
||
// CheckpointObject puts inputs in the `__inputs` field of the state. |
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.
Out of scope here but I am curious now do we understand why it's needed? Throwing a sentence on why we're doing this could be interesting.
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.
// Read returns the outputs and the updated inputs of the resource. | ||
Read(ctx context.Context, urn resource.URN, id string, oldInputs, oldOutputs resource.PropertyMap) (outputs map[string]any, inputs resource.PropertyMap, exists bool, err error) | ||
Read(ctx context.Context, urn resource.URN, id string, oldInputs, oldOutputs resource.PropertyMap) (outputs resource.PropertyMap, inputs resource.PropertyMap, exists bool, err error) |
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.
Love a little more type-safety here.
@@ -12,11 +13,11 @@ type CustomResource interface { | |||
// Check validates and transforms the inputs of the resource. | |||
Check(ctx context.Context, urn resource.URN, randomSeed []byte, inputs, state resource.PropertyMap, defaultTags map[string]string) (resource.PropertyMap, []ValidationFailure, error) | |||
// Create creates a new resource in the cloud provider and returns its unique identifier and outputs. | |||
Create(ctx context.Context, urn resource.URN, inputs resource.PropertyMap) (identifier *string, outputs map[string]any, err error) | |||
Create(ctx context.Context, urn resource.URN, inputs resource.PropertyMap, timeout time.Duration) (identifier *string, outputs resource.PropertyMap, err error) |
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 seems like a breaking change but we are expecting this interface to be internal? .. We're on v1.5.0
. Nothing consumes it in other codebases? Should we work harder here as in introducing a side-by-side interface?
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, this interface is internal. There's no way somebody could use this interface and plug it into aws-native unless they fork aws-native. It's used internally to wrap arbitrary custom resources:
pulumi-aws-native/provider/pkg/provider/provider.go
Lines 509 to 511 in 0166a63
p.customResources = map[string]resources.CustomResource{ | |
metadata.ExtensionResourceToken: resources.NewExtensionResource(p.ccc), | |
} |
I added unit tests for the provider's CRUD operations. Coverage wise we should be good now and I managed to uncover a bug: #1796 |
Previously it was assumed that the custom resources do not concern themselves with secretness or handle timeouts.
But this is necessary to support CloudFormation based Custom Resources.
Those can contain secret outputs and support configuring timeouts.
This change modifies the
CustomResource
interface to accommodate those requirements.In detail this means that the Create/Update/Read lifecycle methods now returns a
PropertyMap
instead of a genericmap[string]interface{}
and take a timeoutparameter.
For reviewing this change, I'd first recommend having a look at the changes to the
CustomResource
interface inprovider/pkg/resources/custom.go
and then double check the refactoring changes resulting in that.This change also introduces tests for the provider's CRUD lifecycle. As part of doing that, I added mocks using
uber/gomock
.Relates to pulumi/pulumi-cdk#109