Skip to content

Commit

Permalink
Fix automatic aliasing of muxed providers
Browse files Browse the repository at this point in the history
Fixes #1937

This PR fixes the automatic aliasing of muxed providers by dispatching a ResourceMap Clone operation to the sub-map that
owns the key being cloned and making PF resource maps mutable.
  • Loading branch information
t0yv0 committed May 8, 2024
1 parent 012ac65 commit bfaea6b
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 92 deletions.
53 changes: 4 additions & 49 deletions pf/internal/muxer/muxer.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package muxer

import (
"fmt"
"sort"
"strings"

"context"
Expand All @@ -26,7 +25,6 @@ import (
"github.com/pulumi/pulumi-terraform-bridge/pf/internal/schemashim"
"github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge"
shim "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim"
shimSchema "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim/schema"
"github.com/pulumi/pulumi-terraform-bridge/x/muxer"
"github.com/pulumi/pulumi/sdk/v3/go/common/tokens"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
Expand Down Expand Up @@ -124,10 +122,10 @@ func (m *ProviderShim) DataSourceIsPF(token string) bool {
//
// `provider` will be the `len(m.MuxedProviders)` when mappings are computed.
func (m *ProviderShim) extend(provider shim.Provider) ([]string, []string) {
res, conflictingResources := union(m.resources, provider.ResourcesMap())

data, conflictingDataSources := union(m.dataSources, provider.DataSourcesMap())

res := newUnionResourceMap(m.resources, provider.ResourcesMap())
conflictingResources := res.ConflictingKeys()
data := newUnionResourceMap(m.dataSources, provider.DataSourcesMap())
conflictingDataSources := data.ConflictingKeys()
m.resources = res
m.dataSources = data
m.MuxedProviders = append(m.MuxedProviders, provider)
Expand Down Expand Up @@ -255,46 +253,3 @@ func (p *simpleSchemaProvider) DataSourcesMap() shim.ResourceMap {
}

var _ shim.Provider = (*simpleSchemaProvider)(nil)

func union(baseline, extension shim.ResourceMap) (shim.ResourceMap, []string) {
union, conflictingKeys := mapUnion(toResourceMap(baseline), toResourceMap(extension))
return shimSchema.ResourceMap(union), conflictingKeys
}

func toResourceMap(rmap shim.ResourceMap) shimSchema.ResourceMap {
m := map[string]shim.Resource{}
rmap.Range(func(key string, value shim.Resource) bool {
m[key] = value
return true
})
return m
}

func mapUnion[T any](baseline, extension map[string]T) (map[string]T, []string) {
u := copyMap(baseline)

var conflictingKeys []string

for k, v := range extension {
if _, conflict := baseline[k]; conflict {
conflictingKeys = append(conflictingKeys, k)
continue
}
u[k] = v
}

sort.Strings(conflictingKeys)

return u, conflictingKeys
}

func copyMap[K comparable, V any](m map[K]V) map[K]V {
if m == nil {
return nil
}
out := make(map[K]V, len(m))
for k, v := range m {
out[k] = v
}
return out
}
11 changes: 4 additions & 7 deletions pf/internal/schemashim/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ import (
)

type SchemaOnlyProvider struct {
ctx context.Context
tf pfprovider.Provider
ctx context.Context
tf pfprovider.Provider
resourceMap shim.ResourceMap
}

func (p *SchemaOnlyProvider) PfProvider() pfprovider.Provider {
Expand All @@ -45,11 +46,7 @@ func (p *SchemaOnlyProvider) Schema() shim.SchemaMap {
}

func (p *SchemaOnlyProvider) ResourcesMap() shim.ResourceMap {
resources, err := pfutils.GatherResources(context.TODO(), p.tf)
if err != nil {
panic(err)
}
return &schemaOnlyResourceMap{resources}
return p.resourceMap
}

func (p *SchemaOnlyProvider) DataSourcesMap() shim.ResourceMap {
Expand Down
41 changes: 8 additions & 33 deletions pf/internal/schemashim/resource_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,16 @@ package schemashim
import (
"github.com/pulumi/pulumi-terraform-bridge/pf/internal/pfutils"
shim "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim"
"github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim/schema"
)

type schemaOnlyResourceMap struct {
resources pfutils.Resources
}

var _ shim.ResourceMap = (*schemaOnlyResourceMap)(nil)

func (m *schemaOnlyResourceMap) Len() int {
return len(m.resources.All())
}

func (m *schemaOnlyResourceMap) Get(key string) shim.Resource {
n := pfutils.TypeName(key)
s := m.resources.Schema(n)
return &schemaOnlyResource{s}
}

func (m *schemaOnlyResourceMap) GetOk(key string) (shim.Resource, bool) {
n := pfutils.TypeName(key)
if !m.resources.Has(n) {
return nil, false
}
return m.Get(key), true
}

func (m *schemaOnlyResourceMap) Range(each func(key string, value shim.Resource) bool) {
for _, name := range m.resources.All() {
// Resource map needs to support Set (mutability) for RenameResourceWithAlias.
func newSchemaOnlyResourceMap(resources pfutils.Resources) shim.ResourceMap {
m := schema.ResourceMap{}
for _, name := range resources.All() {
key := string(name)
if !each(key, m.Get(key)) {
return
}
v := resources.Schema(name)
m[key] = &schemaOnlyResource{v}
}
}

func (*schemaOnlyResourceMap) Set(key string, value shim.Resource) {
panic("Set not supported - is it possible to treat this as immutable?")
return m
}
11 changes: 9 additions & 2 deletions pf/internal/schemashim/schemashim.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,19 @@ import (
"context"

pfprovider "github.com/hashicorp/terraform-plugin-framework/provider"
"github.com/pulumi/pulumi-terraform-bridge/pf/internal/pfutils"
shim "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim"
)

func ShimSchemaOnlyProvider(ctx context.Context, provider pfprovider.Provider) shim.Provider {
resources, err := pfutils.GatherResources(ctx, provider)
if err != nil {
panic(err)
}
resourceMap := newSchemaOnlyResourceMap(resources)
return &SchemaOnlyProvider{
ctx: ctx,
tf: provider,
ctx: ctx,
tf: provider,
resourceMap: resourceMap,
}
}
3 changes: 2 additions & 1 deletion pkg/tfbridge/info/rename.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"fmt"
"strings"

shim "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim"
"github.com/pulumi/pulumi/sdk/v3/go/common/tokens"
)

Expand Down Expand Up @@ -59,7 +60,7 @@ func (p *Provider) RenameResourceWithAlias(resourceName string, legacyTok tokens
currentInfo.Tok.Name().String()))
p.Resources[resourceName] = &currentInfo
p.Resources[legacyResourceName] = &legacyInfo
p.P.ResourcesMap().Set(legacyResourceName, p.P.ResourcesMap().Get(resourceName))
shim.CloneResource(p.P.ResourcesMap(), resourceName, legacyResourceName)
}

func (p *Provider) RenameDataSource(resourceName string, legacyTok tokens.ModuleMember, newTok tokens.ModuleMember,
Expand Down
14 changes: 14 additions & 0 deletions pkg/tfshim/shim.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,20 @@ type ResourceMap interface {
Set(key string, value Resource)
}

type ResourceMapWithClone interface {
ResourceMap
Clone(oldKey, newKey string) error
}

func CloneResource(rm ResourceMap, oldKey string, newKey string) {
switch rm := rm.(type) {
case ResourceMapWithClone:
rm.Clone(oldKey, newKey)

Check failure on line 199 in pkg/tfshim/shim.go

View workflow job for this annotation

GitHub Actions / Test and Lint / lint

Error return value of `rm.Clone` is not checked (errcheck)
default:
rm.Set(newKey, rm.Get(oldKey))
}
}

type Provider interface {
Schema() SchemaMap
ResourcesMap() ResourceMap
Expand Down

0 comments on commit bfaea6b

Please sign in to comment.