diff --git a/changelog/pending/20230314--sdk-go--fixes-use-of-provider-option-from-parent-resources-with-mismatched-packages.yaml b/changelog/pending/20230314--sdk-go--fixes-use-of-provider-option-from-parent-resources-with-mismatched-packages.yaml new file mode 100644 index 000000000000..e8e8e260a091 --- /dev/null +++ b/changelog/pending/20230314--sdk-go--fixes-use-of-provider-option-from-parent-resources-with-mismatched-packages.yaml @@ -0,0 +1,4 @@ +changes: +- type: fix + scope: sdk/go + description: Fixes use of Provider option from parent resources with mismatched packages. diff --git a/sdk/go/pulumi/context.go b/sdk/go/pulumi/context.go index 04648fd71750..f83b71cfd627 100644 --- a/sdk/go/pulumi/context.go +++ b/sdk/go/pulumi/context.go @@ -1062,8 +1062,8 @@ func (ctx *Context) mergeProviders(t string, parent Resource, provider ProviderR // getProvider gets the provider for the resource. func getProvider(t string, provider ProviderResource, providers map[string]ProviderResource) ProviderResource { - if provider == nil { - pkg := getPackage(t) + pkg := getPackage(t) + if provider == nil || provider.getPackage() != pkg { provider = providers[pkg] } return provider diff --git a/sdk/go/pulumi/resource_test.go b/sdk/go/pulumi/resource_test.go index 783401b2a419..a7220c639281 100644 --- a/sdk/go/pulumi/resource_test.go +++ b/sdk/go/pulumi/resource_test.go @@ -784,6 +784,63 @@ func TestComponentResourcePropagatesProvider(t *testing.T) { }) } +// Verifies that if we pass an explicit provider to the provider plugin +// via the Provider() option, +// that the provider propagates this down to its children. +// +// Regression test for https://github.com/pulumi/pulumi/issues/12430 +func TestRemoteComponentResourcePropagatesProvider(t *testing.T) { + t.Parallel() + + err := RunErr(func(ctx *Context) error { + var prov struct{ ProviderResourceState } + require.NoError(t, + ctx.RegisterResource("pulumi:providers:aws", "myprovider", nil /* props */, &prov), + "error registering provider") + + var comp struct{ ResourceState } + require.NoError(t, + ctx.RegisterRemoteComponentResource("awsx:ec2:Vpc", "myvpc", nil /* props */, &comp, Provider(&prov)), + "error registering component") + + var custom struct{ ResourceState } + require.NoError(t, + ctx.RegisterResource("aws:ec2/vpc:Vpc", "myvpc", nil /* props */, &custom, Parent(&comp)), + "error registering resource") + + assert.True(t, &prov == custom.provider, "provider not propagated: %v", custom.provider) + return nil + }, WithMocks("project", "stack", &testMonitor{ + NewResourceF: func(args MockResourceArgs) (string, resource.PropertyMap, error) { + switch args.Name { + case "myprovider": + assert.Equal(t, "pulumi:providers:aws", args.RegisterRPC.Type) + + case "myvpc": + // The remote component resource and the custom resource both + // have the same name. + // + // However, only the custom resource should have the provider set. + switch args.RegisterRPC.Type { + case "awsx:ec2:Vpc": + assert.Empty(t, args.Provider, + "provider must not be set on remote component resource") + + case "aws:ec2/vpc:Vpc": + assert.NotEmpty(t, args.Provider, + "provider must be set on component resource") + + default: + assert.Fail(t, "unexpected resource type: %s", args.RegisterRPC.Type) + } + } + + return args.Name, resource.PropertyMap{}, nil + }, + })) + assert.NoError(t, err) +} + // Verifies that Provider takes precedence over Providers. func TestResourceProviderVersusProviders(t *testing.T) { t.Parallel()