Skip to content

Commit

Permalink
sdk/go: Don't use Provider for type if package doesn't match
Browse files Browse the repository at this point in the history
In #12296, we started correctly interpreting the Provider argument
per other SDKs. but this introduced a regression:
the Provider field is now set for resources with mismatched types.

This results in a scenario where a provider foo for package X
is passed to a resource bar with package Y,
with the intent of plumbing it to bar's descendants,
but bar attempts to incorrectly use the provider directly.

    foo := NewXProvider()
    bar := NewYThing("bar", Provider(foo))
    // ...
    baz := NewXThing("baz", Parent(bar)) // should use foo

This worked previously, but with #12296, this fails
because NewYThing attempts to use Provider foo directly.

To fix this, we need to prevent NewYThing from using a provider
that does not match the package that it belongs to.
We had to make a similar change to the Python SDK in #12292.

https://github.com/pulumi/pulumi/blob/477e0c97660bdbeb28a142057899792d52e63a0b/sdk/python/lib/pulumi/resource.py#L925-L927

The regression test is specific to remote component resources
per #12430, but the issue would be caused even for normal component
resources before this.

Resolves #12430
  • Loading branch information
abhinav committed Mar 14, 2023
1 parent 477e0c9 commit ef6036a
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 2 deletions.
@@ -0,0 +1,4 @@
changes:
- type: fix
scope: sdk/go
description: Fixes use of Provider option from parent resources with mismatched packages.
4 changes: 2 additions & 2 deletions sdk/go/pulumi/context.go
Expand Up @@ -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
Expand Down
57 changes: 57 additions & 0 deletions sdk/go/pulumi/resource_test.go
Expand Up @@ -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()
Expand Down

0 comments on commit ef6036a

Please sign in to comment.