Skip to content

Commit

Permalink
implement shim.Provider for planResourceChangeImpl
Browse files Browse the repository at this point in the history
  • Loading branch information
VenelinMartinov committed Jan 27, 2025
1 parent 140a0fb commit b3ac253
Showing 1 changed file with 143 additions and 0 deletions.
143 changes: 143 additions & 0 deletions pkg/tfshim/sdk-v2/provider2.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ import (
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
"github.com/hashicorp/terraform-plugin-go/tftypes"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
testing "github.com/mitchellh/go-testing-interface"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"

"github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge/log"
Expand Down Expand Up @@ -168,10 +170,150 @@ type planResourceChangeImpl struct {
tf *schema.Provider
server *grpcServer
planEditFunc PlanStateEditFunc
// All resources to serve schema.
resources map[string]*schema.Resource
}

var _ planResourceChangeProvider = (*planResourceChangeImpl)(nil)

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

func (p *planResourceChangeImpl) Configure(ctx context.Context, c shim.ResourceConfig) error {
// See ConfigureProvider e.g.
// https://github.com/hashicorp/terraform-plugin-sdk/blob/main/helper/schema/grpc_provider.go#L564
ctxHack := context.WithValue(ctx, schema.StopContextKey, p.stopContext(context.Background()))
return errors(p.tf.Configure(ctxHack, configFromShim(c)))
}

func (p *planResourceChangeImpl) stopContext(ctx context.Context) context.Context {
// TODO may want to follow StopContext implementation to make sure calling calling p.Stop()
// cancels the context returned here.
//
// See: https://github.com/hashicorp/terraform-plugin-sdk/blob/main/helper/schema/grpc_provider.go#L60C1-L60C80
return ctx
}

func (p *planResourceChangeImpl) Schema() shim.SchemaMap {
return v2SchemaMap(p.tf.Schema)
}

func (p *planResourceChangeImpl) ResourcesMap() shim.ResourceMap {
return &v2ResourceCustomMap{
resources: p.resources,
pack: func(token string, res *schema.Resource) shim.Resource {
i := p.Importer(token)
return &v2Resource2{v2Resource{res}, i, token}
},
}
}

func (p *planResourceChangeImpl) DataSourcesMap() shim.ResourceMap {
return v2ResourceMap(p.tf.DataSourcesMap)
}

func (p *planResourceChangeImpl) InternalValidate() error {
return p.tf.InternalValidate()
}

func (p *planResourceChangeImpl) Validate(_ context.Context, c shim.ResourceConfig) ([]string, []error) {
return warningsAndErrors(p.tf.Validate(configFromShim(c)))
}

func (p *planResourceChangeImpl) ValidateResource(
_ context.Context, t string, c shim.ResourceConfig,
) ([]string, []error) {
return warningsAndErrors(p.tf.ValidateResource(t, configFromShim(c)))
}

func (p *planResourceChangeImpl) ValidateDataSource(
_ context.Context, t string, c shim.ResourceConfig,
) ([]string, []error) {
return warningsAndErrors(p.tf.ValidateDataSource(t, configFromShim(c)))
}

func (p *planResourceChangeImpl) ReadDataDiff(
ctx context.Context,
t string,
c shim.ResourceConfig,
) (shim.InstanceDiff, error) {
resource, ok := p.tf.DataSourcesMap[t]
if !ok {
return nil, fmt.Errorf("unknown resource %v", t)
}

config := configFromShim(c)
rawConfig := makeResourceRawConfig(config, resource)

diff, err := resource.Diff(ctx, nil, config, p.tf.Meta())
if diff != nil {
diff.RawConfig = rawConfig
}
return diffToShim(diff), err
}

func (p *planResourceChangeImpl) ReadDataApply(
ctx context.Context,
t string,
d shim.InstanceDiff,
) (shim.InstanceState, error) {
r, ok := p.tf.DataSourcesMap[t]
if !ok {
return nil, fmt.Errorf("unknown resource %v", t)
}
state, diags := r.ReadDataApply(ctx, diffFromShim(d), p.tf.Meta())
return stateToShim(r, state), errors(diags)
}

func (p *planResourceChangeImpl) Meta(_ context.Context) interface{} {
return p.tf.Meta()
}

func (p *planResourceChangeImpl) Stop(_ context.Context) error {
return nil
}

func (p *planResourceChangeImpl) InitLogging(_ context.Context) {
logging.SetOutput(&testing.RuntimeT{})
}

func (p *planResourceChangeImpl) NewResourceConfig(
_ context.Context, object map[string]interface{},
) shim.ResourceConfig {
return v2ResourceConfig{&terraform.ResourceConfig{
Raw: object,
Config: object,
}}
}

func (p *planResourceChangeImpl) NewProviderConfig(
_ context.Context, object map[string]interface{},
) shim.ResourceConfig {
tfConfig := &terraform.ResourceConfig{
Raw: object,
Config: object,
}
typ := schema.InternalMap(p.tf.Schema).CoreConfigSchema().ImpliedType()
ctyVal, err := recoverCtyValueOfObjectType(typ, object)
if err != nil {
glog.V(9).Infof("Failed to recover cty value of object type: %v, falling back to old behaviour", err)
return v2ResourceConfig{tfConfig}
}

tfConfig.CtyValue = ctyVal
return v2ResourceConfig{tfConfig}
}

func (p *planResourceChangeImpl) IsSet(_ context.Context, v interface{}) ([]interface{}, bool) {
if set, ok := v.(*schema.Set); ok {
return set.List(), true
}
return nil, false
}

func (p *planResourceChangeImpl) SupportsUnknownCollections() bool {
return true
}

// If the user specifies custom timeout overrides for the resource, encode them in the magic `timeouts` key under config
// and plannedState. This is how TF communicates this information on the gRPC protocol. The schema default timeouts need
// not be specially encoded because the gRPC implementation already respects them. A slight complication here is that
Expand Down Expand Up @@ -943,6 +1085,7 @@ func newProviderWithPlanResourceChange(
server: &grpcServer{
gserver: p.GRPCProvider().(*schema.GRPCProviderServer),
},
resources: p.ResourcesMap,
},
usePlanResourceChange: filter,
}
Expand Down

0 comments on commit b3ac253

Please sign in to comment.