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

Allow component resources to inherit providers from component resources #10933

Merged
merged 1 commit into from Oct 20, 2022

Conversation

iwahbe
Copy link
Member

@iwahbe iwahbe commented Oct 5, 2022

Description

Fixes #10640

Checklist

  • I have added tests that prove my fix is effective or that my feature works
  • I have run make changelog and committed the changelog/pending/<file> documenting my change
  • Yes, there are changes in this PR that warrants bumping the Pulumi Service API version

@pulumi-bot
Copy link
Contributor

pulumi-bot commented Oct 5, 2022

Changelog

[uncommitted] (2022-10-20)

Bug Fixes

  • [cli/engine] Component Resources inherit thier parents providers map
    #10933

Copy link
Member

@Frassle Frassle left a 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?

@iwahbe iwahbe force-pushed the iwahbe/10640/inherit-through-component-resources branch from a932ea4 to 9f88b05 Compare October 5, 2022 21:06
@iwahbe
Copy link
Member Author

iwahbe commented Oct 5, 2022

@Frassle This can be fixed in the engine. It's a cleaner fix but requires bifurcating providers logic. It needs to occur before remote component resources are constructed, which means it needs to live in the resmon.

@iwahbe iwahbe self-assigned this Oct 5, 2022
@justinvp
Copy link
Member

justinvp commented Oct 6, 2022

Any tests?

@iwahbe
Copy link
Member Author

iwahbe commented Oct 6, 2022

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.

@Frassle
Copy link
Member

Frassle commented Oct 7, 2022

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:
Copy link
Member

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?

Copy link
Member Author

@iwahbe iwahbe Oct 7, 2022

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:

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.

@iwahbe
Copy link
Member Author

iwahbe commented Oct 7, 2022

Writing the necessary test is taking longer than I thought. This is what I'm thinking:
We need a test that looks like this:

  1. Create provider p of package pkgA.
  2. Create language specific component c1, passing providers=[p].
  3. c1 creates MLC component c2 of package pkgA as a child, passing parent=c1 on creation.
  4. c2 creates custom resource r of package pkgB.
  5. We assert that r was created with provider p.

@iwahbe
Copy link
Member Author

iwahbe commented Oct 7, 2022

You could test this in pulumi_tests.go, there's a lot of other engine tests there.

It doesn't look like pulumi_test.go puts resmon under test (which is where the change in engine logic is located).

@Frassle
Copy link
Member

Frassle commented Oct 7, 2022

It doesn't look like pulumi_test.go puts resmon under test (which is where the change in engine logic is located).

"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).

@iwahbe iwahbe requested a review from Frassle October 10, 2022 19:19
@iwahbe
Copy link
Member Author

iwahbe commented Oct 10, 2022

It doesn't look like pulumi_test.go puts resmon under test (which is where the change in engine logic is located).

"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.

@iwahbe iwahbe force-pushed the iwahbe/10640/inherit-through-component-resources branch 3 times, most recently from 48b929e to 12c75e9 Compare October 14, 2022 01:09
@@ -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...)
Copy link
Member

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?

Copy link
Member Author

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"

@@ -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() {
Copy link
Member

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?

Copy link
Member Author

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.

Copy link
Member

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.

@iwahbe iwahbe requested a review from Frassle October 18, 2022 22:32
Copy link
Member

@justinvp justinvp left a 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 Show resolved Hide resolved
@@ -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() {
Copy link
Member

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/component_setup.sh Outdated Show resolved Hide resolved
tests/integration/construct_nested_component/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
@iwahbe iwahbe force-pushed the iwahbe/10640/inherit-through-component-resources branch from 1c220f3 to e387ba8 Compare October 20, 2022 22:36
@iwahbe
Copy link
Member Author

iwahbe commented Oct 20, 2022

bors r+

bors bot added a commit that referenced this pull request Oct 20, 2022
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>
@iwahbe
Copy link
Member Author

iwahbe commented Oct 20, 2022

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.

@iwahbe iwahbe force-pushed the iwahbe/10640/inherit-through-component-resources branch from 701fb7a to e387ba8 Compare October 20, 2022 23:11
@bors
Copy link
Contributor

bors bot commented Oct 20, 2022

Canceled.

@iwahbe
Copy link
Member Author

iwahbe commented Oct 20, 2022

bors r+

@bors
Copy link
Contributor

bors bot commented Oct 20, 2022

Build succeeded:

@bors bors bot merged commit a5cac1d into master Oct 20, 2022
@bors bors bot deleted the iwahbe/10640/inherit-through-component-resources branch October 20, 2022 23:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Component children of component resources don't inherit their parents providers
4 participants