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

Add token mapping strategies with inferred fallback #2882

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions pkg/tfbridge/tokens/fallback_strategy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package tokens

import "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge/info"

func tokenStrategyWithFallback(
strategy Strategy,
fallback Strategy,
) Strategy {
resourceFallback := func(tfToken string, elem *info.Resource) error {
if err := strategy.Resource(tfToken, elem); err != nil {
return fallback.Resource(tfToken, elem)
}
return nil
}
dataSourceFallback := func(tfToken string, elem *info.DataSource) error {
if err := strategy.DataSource(tfToken, elem); err != nil {
return fallback.DataSource(tfToken, elem)
}
return nil
}
return Strategy{
Resource: resourceFallback,
DataSource: dataSourceFallback,
}
}
34 changes: 29 additions & 5 deletions pkg/tfbridge/tokens/known_modules.go
VenelinMartinov marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
func knownModules[T info.Resource | info.DataSource](
prefix, defaultModule string, modules []string,
apply func(string, string, *T, error) error,
moduleTransform func(string) string,
moduleTransform func(string) (string, error),
VenelinMartinov marked this conversation as resolved.
Show resolved Hide resolved
) info.ElementStrategy[T] {
return func(tfToken string, elem *T) error {
var tk string
Expand All @@ -53,9 +53,15 @@ func knownModules[T info.Resource | info.DataSource](
}
var err error
if mod == "" {
err = fmt.Errorf("could not find a module that prefixes '%s' in '%#v'", tk, modules)
return apply("", upperCamelCase(tk), elem,
fmt.Errorf("could not find a module that prefixes '%s' in '%#v'", tk, modules))
}
return apply(moduleTransform(mod), upperCamelCase(strings.TrimPrefix(tk, mod)), elem, err)
transformed, err := moduleTransform(mod)
if err != nil {
return apply("", upperCamelCase(tk), elem,
fmt.Errorf("could not transform module '%s': %w", mod, err))
}
return apply(transformed, upperCamelCase(strings.TrimPrefix(tk, mod)), elem, nil)
}
}

Expand All @@ -72,9 +78,9 @@ func KnownModules(

return Strategy{
Resource: knownModules(tfPackagePrefix, defaultModule, modules,
knownResource(finalize), camelCase),
knownResource(finalize), func(s string) (string, error) { return camelCase(s), nil }),
DataSource: knownModules(tfPackagePrefix, defaultModule, modules,
knownDataSource(finalize), camelCase),
knownDataSource(finalize), func(s string) (string, error) { return camelCase(s), nil }),
}
}

Expand Down Expand Up @@ -111,3 +117,21 @@ func knownDataSource(finalize Make) func(mod, tk string, d *info.DataSource, err
return nil
}
}

func KnownModulesWithInferredFallback(
p *info.Provider,
tfPackagePrefix, defaultModule string, modules []string, finalize Make,
opts *InferredModulesOpts,
) (Strategy, error) {
if opts.TfPkgPrefix == "" {
opts.TfPkgPrefix = tfPackagePrefix
}
inferred, err := InferredModules(p, finalize, opts)
if err != nil {
return Strategy{}, err
}
return tokenStrategyWithFallback(
KnownModules(tfPackagePrefix, defaultModule, modules, finalize),
inferred,
), nil
}
29 changes: 23 additions & 6 deletions pkg/tfbridge/tokens/mapped_modules.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
package tokens

import (
"fmt"
"sort"

"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
"github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge/info"
)

// A strategy for assigning tokens to a hand generated set of modules with an arbitrary
Expand All @@ -33,16 +34,17 @@ func MappedModules(
}
sort.Sort(sort.Reverse(sort.StringSlice(mods)))

transform := func(tf string) string {
transform := func(tf string) (string, error) {
s, ok := modules[tf]
if !ok && tf == defaultModule {
// We pass through the default module as is, so it might not be in
// `modules`. We need to catch that and return as is.
return tf
return tf, nil
}
assert := "Because any mod selected must be from mods, it is guaranteed to be in modules, got %#v"
contract.Assertf(ok, assert, tf)
return s
if !ok {
return "", fmt.Errorf("could not find a module that prefixes '%s' in '%#v'", tf, mods)
}
return s, nil
VenelinMartinov marked this conversation as resolved.
Show resolved Hide resolved
}

return Strategy{
Expand All @@ -52,3 +54,18 @@ func MappedModules(
knownDataSource(finalize), transform),
}
}

func MappedModulesWithInferredFallback(
p *info.Provider,
tfPackagePrefix, defaultModule string, modules map[string]string, finalize Make,
opts *InferredModulesOpts,
) (Strategy, error) {
inferred, err := InferredModules(p, finalize, opts)
if err != nil {
return Strategy{}, err
}
return tokenStrategyWithFallback(
MappedModules(tfPackagePrefix, defaultModule, modules, finalize),
inferred,
), nil
}
83 changes: 83 additions & 0 deletions pkg/tfbridge/tokens_test.go
VenelinMartinov marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,46 @@ func TestTokensKnownModules(t *testing.T) {
}, info.Resources)
}

func TestTokensKnownModulesWithInferredFallback(t *testing.T) {
t.Parallel()
info := tfbridge.ProviderInfo{
P: (&schema.Provider{
ResourcesMap: schema.ResourceMap{
"cs101_fizz_buzz_one_five": nil,
"cs101_fizz_three": nil,
"cs101_fizz_three_six": nil,
"cs101_buzz_five": nil,
"cs101_buzz_ten": nil,
},
}).Shim(),
}

strategy, err := tokens.KnownModulesWithInferredFallback(&info,
"cs101_", "", []string{
"fizz_", "fizz_buzz_",
}, func(module, name string) (string, error) {
return fmt.Sprintf("cs101:%s:%s", module, name), nil
}, &tokens.InferredModulesOpts{
MinimumModuleSize: 2,
MimimumSubmoduleSize: 2,
})
require.NoError(t, err)

err = info.ComputeTokens(tfbridge.Strategy{
Resource: strategy.Resource,
})
require.NoError(t, err)

assert.Equal(t, map[string]*tfbridge.ResourceInfo{
"cs101_fizz_buzz_one_five": {Tok: "cs101:fizzBuzz:OneFive"},
"cs101_fizz_three": {Tok: "cs101:fizz:Three"},
"cs101_fizz_three_six": {Tok: "cs101:fizz:ThreeSix"},
// inferred
"cs101_buzz_five": {Tok: "cs101:buzz:Five"},
"cs101_buzz_ten": {Tok: "cs101:buzz:Ten"},
}, info.Resources)
}

func TestTokensKnownModulesAlreadyMapped(t *testing.T) {
t.Parallel()
info := tfbridge.ProviderInfo{
Expand Down Expand Up @@ -242,6 +282,49 @@ func TestTokensMappedModules(t *testing.T) {
}, info.Resources)
}

func TestTokensMappedModulesWithInferredFallback(t *testing.T) {
t.Parallel()
info := tfbridge.ProviderInfo{
P: (&schema.Provider{
ResourcesMap: schema.ResourceMap{
"cs101_fizz_buzz_one_five": nil,
"cs101_fizz_three": nil,
"cs101_fizz_three_six": nil,
"cs101_buzz_five": nil,
"cs101_buzz_ten": nil,
},
}).Shim(),
}
strategy, err := tokens.MappedModulesWithInferredFallback(
&info,
"cs101_", "", map[string]string{
"fizz_": "fIzZ",
"fizz_buzz_": "fizZBuzz",
},
func(module, name string) (string, error) {
return fmt.Sprintf("cs101:%s:%s", module, name), nil
},
&tokens.InferredModulesOpts{
MinimumModuleSize: 2,
MimimumSubmoduleSize: 2,
},
)
require.NoError(t, err)

err = info.ComputeTokens(tfbridge.Strategy{
Resource: strategy.Resource,
})
require.NoError(t, err)
assert.Equal(t, map[string]*tfbridge.ResourceInfo{
"cs101_fizz_buzz_one_five": {Tok: "cs101:fizZBuzz:OneFive"},
"cs101_fizz_three": {Tok: "cs101:fIzZ:Three"},
"cs101_fizz_three_six": {Tok: "cs101:fIzZ:ThreeSix"},
// inferred
"cs101_buzz_five": {Tok: "cs101:buzz:Five"},
"cs101_buzz_ten": {Tok: "cs101:buzz:Ten"},
}, info.Resources)
}

func TestTokensMostSpecificMappedModules(t *testing.T) {
t.Parallel()
info := tfbridge.ProviderInfo{
Expand Down
Loading