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

Detailed TF schema dump #2125

Closed
wants to merge 12 commits into from
16 changes: 16 additions & 0 deletions pf/internal/muxer/muxer.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,18 @@ func (m *ProviderShim) extend(provider shim.Provider) ([]string, []string) {
return conflictingResources, conflictingDataSources
}

func (m *ProviderShim) DetailedSchemaDump() []byte {
for _, p := range m.MuxedProviders {
defer func() {
if r := recover(); r != nil {
contract.IgnoreError(fmt.Errorf("DetailedSchemaDump failed: %v", r))
}
}()
return p.DetailedSchemaDump()
}
return nil
}

func newProviderShim(provider shim.Provider) ProviderShim {
return ProviderShim{
simpleSchemaProvider: simpleSchemaProvider{
Expand Down Expand Up @@ -253,4 +265,8 @@ func (p *simpleSchemaProvider) DataSourcesMap() shim.ResourceMap {
return p.dataSources
}

func (p *simpleSchemaProvider) DetailedSchemaDump() []byte {
panic("Unsupported")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of panicking, can we just return nil. That way we can leave actual panics uncaught.

Suggested change
panic("Unsupported")
return nil

}

var _ shim.Provider = (*simpleSchemaProvider)(nil)
4 changes: 4 additions & 0 deletions pf/internal/schemashim/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ func (p *SchemaOnlyProvider) Config(ctx context.Context) (tftypes.Object, error)
return schema.Type().TerraformType(ctx).(tftypes.Object), nil
}

func (p *SchemaOnlyProvider) DetailedSchemaDump() []byte {
panic("Unsupported")
}

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

func (p *SchemaOnlyProvider) Schema() shim.SchemaMap {
Expand Down
4 changes: 4 additions & 0 deletions pf/proto/protov6.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,7 @@ func (p Provider) DataSourcesMap() shim.ResourceMap {
}
return resourceMap(v.DataSourceSchemas)
}

func (p Provider) DetailedSchemaDump() []byte {
panic("Unsupported")
}
18 changes: 18 additions & 0 deletions pf/tfbridge/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
//
// info.P must be constructed with ShimProvider or ShimProviderWithContext.
func Main(ctx context.Context, pkg string, prov tfbridge.ProviderInfo, meta ProviderMetadata) {
handleGetSchemaFlag(prov)
handleFlags(ctx, prov.Version,
func() (*tfbridge.MarshallableProviderInfo, error) {
pp, err := newProviderWithContext(ctx, prov, meta)
Expand All @@ -54,6 +55,22 @@ func Main(ctx context.Context, pkg string, prov tfbridge.ProviderInfo, meta Prov
}
}

func handleGetSchemaFlag(prov tfbridge.ProviderInfo) {
flags := flag.NewFlagSet("get-schema-flags", flag.ContinueOnError)

dumpSchema := flags.Bool("get-schema", false, "dump provider schema as JSON to stdout")

flags.SetOutput(io.Discard)

err := flags.Parse(os.Args[1:])
contract.IgnoreError(err)

Comment on lines +63 to +67
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does PF need this ceremony when pkg can just call flags.Bool?

	dumpSchema := flags.Bool("get-schema", false, "dump provider schema as JSON to stdout")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleFlags takes a MarshallableProviderInfo, which does not have the required fields for DetailedSchemaDump

if *dumpSchema {
fmt.Print(string(prov.P.DetailedSchemaDump()))
os.Exit(0)
}
}

func handleFlags(
ctx context.Context, version string,
getProviderInfo func() (*tfbridge.MarshallableProviderInfo, error),
Expand Down Expand Up @@ -107,6 +124,7 @@ func MainWithMuxer(ctx context.Context, pkg string, info tfbridge.ProviderInfo,
if len(info.MuxWith) > 0 {
panic("mixin providers via tfbridge.ProviderInfo.MuxWith is currently not supported")
}
handleGetSchemaFlag(info)
handleFlags(ctx, info.Version, func() (*tfbridge.MarshallableProviderInfo, error) {
info := info
return tfbridge.MarshalProviderInfo(&info), nil
Expand Down
6 changes: 6 additions & 0 deletions pkg/tfbridge/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func Main(pkg string, version string, prov ProviderInfo, pulumiSchema []byte) {
flags.SetOutput(io.Discard)

dumpInfo := flags.Bool("get-provider-info", false, "dump provider info as JSON to stdout")
dumpSchema := flags.Bool("get-schema", false, "dump provider schema as JSON to stdout")
providerVersion := flags.Bool("version", false, "get built provider version")

err := flags.Parse(os.Args[1:])
Expand All @@ -62,6 +63,11 @@ func Main(pkg string, version string, prov ProviderInfo, pulumiSchema []byte) {
os.Exit(0)
}

if *dumpSchema {
fmt.Print(string(prov.P.DetailedSchemaDump()))
os.Exit(0)
}

if *providerVersion {
fmt.Println(version)
os.Exit(0)
Expand Down
4 changes: 4 additions & 0 deletions pkg/tfshim/schema/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,7 @@ func (ProviderShim) NewResourceConfig(
func (ProviderShim) IsSet(ctx context.Context, v interface{}) ([]interface{}, bool) {
panic("this provider is schema-only and does not support runtime operations")
}

func (ProviderShim) DetailedSchemaDump() []byte {
panic("this provider is schema-only and does not support runtime operations")
}
4 changes: 4 additions & 0 deletions pkg/tfshim/sdk-v1/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,7 @@ func (p v1Provider) IsSet(_ context.Context, v interface{}) ([]interface{}, bool
}
return nil, false
}

func (p v1Provider) DetailedSchemaDump() []byte {
panic("Unsupported")
}
148 changes: 148 additions & 0 deletions pkg/tfshim/sdk-v2/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package sdkv2

import (
"context"
"encoding/json"
"fmt"
"os"

Expand All @@ -11,6 +12,7 @@ import (
testing "github.com/mitchellh/go-testing-interface"
shim "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/cmdutil"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
)

var _ = shim.Provider(v2Provider{})
Expand Down Expand Up @@ -222,3 +224,149 @@ func (p v2Provider) IsSet(_ context.Context, v interface{}) ([]interface{}, bool
}
return nil, false
}

type tfSchemaMarshaller struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separate files please, not provider.go

Type schema.ValueType
ConfigMode schema.SchemaConfigMode
Required bool
Optional bool
Computed bool
ForceNew bool
DiffSuppressFuncDefined bool
DiffSuppressOnRefresh bool
Default interface{}
DefaultFuncDefined bool
Description string
InputDefault string
StateFuncDefined bool
Elem interface{}
MaxItems int
MinItems int
SetDefined bool
ComputedWhen []string
ConflictsWith []string
ExactlyOneOf []string
AtLeastOneOf []string
RequiredWith []string
Deprecated string
ValidateFuncDefined bool
ValidateDiagFuncDefined bool
Sensitive bool
}

type tfResourceMarshaller struct {
Schema map[string]*tfSchemaMarshaller
SchemaVersion int
MigrateStateDefined bool
StateUpgradersLen int
CustomizeDiffDefined bool
DeprecationMessage string
Description string
UseJSONNumber bool
EnableLegacyTypeSystemApplyErrors bool
EnableLegacyTypeSystemPlanErrors bool
}

type tfProvMarshaller struct {
Schema map[string]*tfSchemaMarshaller
ResourcesMap map[string]*tfResourceMarshaller
DataSourcesMap map[string]*tfResourceMarshaller
ConfigureFuncDefined bool
TerraformVersion string
}

func convertTFSchemaOrResource(s interface{}) interface{} {
if s == nil {
return nil
}
switch s := s.(type) {
case *schema.Schema:
return convertTFSchema(s)
case *schema.Resource:
return convertTfResource(s)
}
panic(fmt.Sprintf("unexpected type %T", s))
}

func convertTFSchema(s *schema.Schema) *tfSchemaMarshaller {
return &tfSchemaMarshaller{
Type: s.Type,
ConfigMode: s.ConfigMode,
Required: s.Required,
Optional: s.Optional,
Computed: s.Computed,
ForceNew: s.ForceNew,
DiffSuppressFuncDefined: s.DiffSuppressFunc != nil,
DiffSuppressOnRefresh: s.DiffSuppressOnRefresh,
Default: s.Default,
DefaultFuncDefined: s.DefaultFunc != nil,
Description: s.Description,
InputDefault: s.InputDefault,
StateFuncDefined: s.StateFunc != nil,
Elem: convertTFSchemaOrResource(s.Elem),
MaxItems: s.MaxItems,
MinItems: s.MinItems,
SetDefined: s.Set != nil,
ComputedWhen: s.ComputedWhen, //nolint:staticcheck
ConflictsWith: s.ConflictsWith,
ExactlyOneOf: s.ExactlyOneOf,
AtLeastOneOf: s.AtLeastOneOf,
RequiredWith: s.RequiredWith,
Deprecated: s.Deprecated,
ValidateFuncDefined: s.ValidateFunc != nil,
ValidateDiagFuncDefined: s.ValidateDiagFunc != nil,
Sensitive: s.Sensitive,
}
}

func convertTfResource(r *schema.Resource) *tfResourceMarshaller {
tfResource := &tfResourceMarshaller{
Schema: make(map[string]*tfSchemaMarshaller),
SchemaVersion: r.SchemaVersion,
MigrateStateDefined: r.MigrateState != nil, //nolint:staticcheck
StateUpgradersLen: len(r.StateUpgraders),
CustomizeDiffDefined: r.CustomizeDiff != nil,
DeprecationMessage: r.DeprecationMessage,
Description: r.Description,
UseJSONNumber: r.UseJSONNumber,
EnableLegacyTypeSystemApplyErrors: r.EnableLegacyTypeSystemApplyErrors,
EnableLegacyTypeSystemPlanErrors: r.EnableLegacyTypeSystemPlanErrors,
}

for k, v := range r.Schema {
tfResource.Schema[k] = convertTFSchema(v)
}

return tfResource
}

func convertTfProv(p *schema.Provider) *tfProvMarshaller {
tfProv := &tfProvMarshaller{
Schema: make(map[string]*tfSchemaMarshaller),
ResourcesMap: make(map[string]*tfResourceMarshaller),
DataSourcesMap: make(map[string]*tfResourceMarshaller),
ConfigureFuncDefined: p.ConfigureFunc != nil, //nolint:staticcheck
TerraformVersion: p.TerraformVersion,
}

for k, v := range p.Schema {
tfProv.Schema[k] = convertTFSchema(v)
}

for k, v := range p.ResourcesMap {
tfProv.ResourcesMap[k] = convertTfResource(v)
}

for k, v := range p.DataSourcesMap {
tfProv.DataSourcesMap[k] = convertTfResource(v)
}

return tfProv
}

func (p v2Provider) DetailedSchemaDump() []byte {
prov := convertTfProv(p.tf)
sch, err := json.Marshal(prov)
contract.AssertNoErrorf(err, "failed to marshal schema")
return sch
}
VenelinMartinov marked this conversation as resolved.
Show resolved Hide resolved
Loading