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
Allow component resources to inherit providers
from component resources
#10933
Conversation
Changelog[uncommitted] (2022-10-20)Bug Fixes
|
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.
Can't this be fixed in the engine rather than the SDKs?
a932ea4
to
9f88b05
Compare
@Frassle This can be fixed in the engine. It's a cleaner fix but requires bifurcating |
Any tests? |
I was trying to come up with a way to test this without writing a full integration test. I'll add an integration test shortly. |
You could test this in pulumi_tests.go, there's a lot of other engine tests there. |
@@ -154,7 +154,7 @@ async def prepare_resource( | |||
# For remote resources, merge any provider opts into a single dict, and then create a new dict with all of the | |||
# resolved provider refs. | |||
provider_refs: Dict[str, Optional[str]] = {} | |||
if remote and opts is not None: | |||
if (remote or not custom) and opts is not None: |
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 is just "not custom" now isn't it? Resources are either LocalComponent, RemoteComponent, or Custom (remote=true, custom=true should be inexpressible). Also is a similar change not needed in the dotnet code?
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 couldn't find the equivalent logic. It is just a branch on custom
:
pulumi/sdk/dotnet/Pulumi/Resources/Resource.cs
Lines 221 to 259 in 85cfd79
if (custom) | |
{ | |
var provider = customOpts?.Provider; | |
if (provider == null) | |
{ | |
if (options.Parent != null) | |
{ | |
// If no provider was given, but we have a parent, then inherit the | |
// provider from our parent. | |
options.Provider = options.Parent.GetProvider(type); | |
} | |
} | |
else | |
{ | |
// If a provider was specified, add it to the providers map under this type's package so that | |
// any children of this resource inherit its provider. | |
var typeComponents = type.Split(":"); | |
if (typeComponents.Length == 3) | |
{ | |
var pkg = typeComponents[0]; | |
this._providers = this._providers.SetItem(pkg, provider); | |
} | |
} | |
} | |
else | |
{ | |
// Note: we checked above that at most one of options.provider or options.providers | |
// is set. | |
// If options.provider is set, treat that as if we were given a array of provider | |
// with that single value in it. Otherwise, take the array of providers, convert it | |
// to a map and combine with any providers we've already set from our parent. | |
var providerList = options.Provider != null | |
? new List<ProviderResource> { options.Provider } | |
: componentOpts?.Providers; | |
this._providers = this._providers.AddRange(ConvertToProvidersMap(providerList)); | |
} |
.NET should work as is.
Writing the necessary test is taking longer than I thought. This is what I'm thinking:
|
It doesn't look like |
"pkg/engine/lifecycletest/pulumi_test.go"? That tests resmon because it tests via sending grpc messages to a resource monitor (either fully over grpc, or just method calls). |
Having though about it longer, I think it's still better to have an integration test here. We ensure that the SDK and the engine are behaving appropriately together. |
48b929e
to
12c75e9
Compare
@@ -41,7 +41,7 @@ func NewResource(ctx *pulumi.Context, name string, echo pulumi.Input, | |||
opts ...pulumi.ResourceOption) (*Resource, error) { | |||
args := &ResourceArgs{Echo: echo} | |||
var resource Resource | |||
err := ctx.RegisterResource("testcomponent:index:Resource", name, args, &resource, opts...) | |||
err := ctx.RegisterResource(providerName+":index:Resource", name, args, &resource, opts...) |
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 don't see providerName declared in here?
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.
Its declared on line 104.
const providerName = "testcomponent" |
pkg/resource/deploy/source_eval.go
Outdated
@@ -1115,6 +1131,13 @@ func (rm *resmon) RegisterResource(ctx context.Context, | |||
|
|||
// If this is a remote component, fetch its provider and issue the construct call. Otherwise, register the resource. | |||
var result *RegisterResult | |||
if !custom { | |||
defer func() { |
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.
Why is this defered? Can't we always just store the provider list as it comes in?
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.
We know the value when we declare the deferred function (L1135), but we don't know the key (URN) to store it at. Note that the defer only finishes the store if we successfully stored an URN.
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.
Should we just move this code down to L1197 when we have the result, so we don't have to have the defer here?
If there's a reason it needs to live here with the defer, it needs a comment explaining why.
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. It took me a while to parse what the test was doing (maybe my brain is just foggy from being sick).
Isn't this only testing the Go SDK? Any reason we're not testing the other SDKs?
Does Java have the same problem? Should we be sending the providers to the engine there as well?
pkg/resource/deploy/source_eval.go
Outdated
@@ -1115,6 +1131,13 @@ func (rm *resmon) RegisterResource(ctx context.Context, | |||
|
|||
// If this is a remote component, fetch its provider and issue the construct call. Otherwise, register the resource. | |||
var result *RegisterResult | |||
if !custom { | |||
defer func() { |
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.
Should we just move this code down to L1197 when we have the result, so we don't have to have the defer here?
If there's a reason it needs to live here with the defer, it needs a comment explaining why.
tests/integration/construct_component/testcomponent2-go/main.go
Outdated
Show resolved
Hide resolved
This is approach needs to occur in `resmon` since `*resmon` dispatches `Construct` calls directly. TS: Send providers map for all components Ensure that `providers` is passed in all SDKs The .NET SDK already does the right thing Add golang integration test Add local dependency Fix test Use new test Get test working Fix nits
1c220f3
to
e387ba8
Compare
bors r+ |
10933: Allow component resources to inherit `providers` from component resources r=iwahbe a=iwahbe <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Fixes #10640 ## Checklist <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Service, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Service API version <!-- `@Pulumi` employees: If yes, you must submit corresponding changes in the service repo. --> Co-authored-by: Ian Wahbe <ian@wahbe.com>
Java has the same semantics as .NET, which already did the correct thing. I added a typescript test here. It was only Go because one SDK was sufficient to test that the engine did there right thing. |
701fb7a
to
e387ba8
Compare
Canceled. |
bors r+ |
Build succeeded: |
Description
Fixes #10640
Checklist
make changelog
and committed thechangelog/pending/<file>
documenting my change