Skip to content

Commit

Permalink
Augment Provider's refresh with RawConfig filled in (#1312)
Browse files Browse the repository at this point in the history
* Refresh with RawConfig filled in

* Adjust to shim.Provider.Refresh interface change

* Change SchemaOnlyProvider so it conforms to Provider

* Add test
  • Loading branch information
iwahbe authored Aug 1, 2023
1 parent a5ef681 commit 9fb0aa5
Show file tree
Hide file tree
Showing 13 changed files with 60 additions and 21 deletions.
7 changes: 6 additions & 1 deletion internal/testprovider/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,12 @@ func ProviderV2() *schemav2.Provider {
MustSetIfUnset(data, "bool_property_value", false)
MustSetIfUnset(data, "number_property_value", 42)
MustSetIfUnset(data, "float_property_value", 99.6767932)
MustSetIfUnset(data, "string_property_value", "ognirts")
if data.Id() == "set-raw-config-id" {
v := data.GetRawConfig().AsValueMap()["raw_config_value"]
MustSet(data, "string_property_value", v.AsString())
} else {
MustSetIfUnset(data, "string_property_value", "ognirts")
}
MustSetIfUnset(data, "array_property_value", []interface{}{"an array"})
MustSetIfUnset(data, "object_property_value", map[string]interface{}{
"property_a": "a",
Expand Down
2 changes: 1 addition & 1 deletion pf/internal/schemashim/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (p *SchemaOnlyProvider) Apply(t string, s shim.InstanceState,
panic("schemaOnlyProvider does not implement runtime operation Apply")
}

func (p *SchemaOnlyProvider) Refresh(t string, s shim.InstanceState) (shim.InstanceState, error) {
func (p *SchemaOnlyProvider) Refresh(string, shim.InstanceState, shim.ResourceConfig) (shim.InstanceState, error) {
panic("schemaOnlyProvider does not implement runtime operation Refresh")
}

Expand Down
7 changes: 6 additions & 1 deletion pkg/tfbridge/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,12 @@ func (p *Provider) Read(ctx context.Context, req *pulumirpc.ReadRequest) (*pulum
}
}

newstate, err := p.tf.Refresh(res.TFName, state)
config, _, err := MakeTerraformConfig(p, oldInputs, res.TF.Schema(), res.Schema.Fields)
if err != nil {
return nil, errors.Wrapf(err, "preparing %s's new property state", urn)
}

newstate, err := p.tf.Refresh(res.TFName, state, config)
if err != nil {
return nil, errors.Wrapf(err, "refreshing %s", urn)
}
Expand Down
26 changes: 22 additions & 4 deletions pkg/tfbridge/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -550,14 +550,19 @@ func TestProviderCheckV2(t *testing.T) {
assert.Equal(t, "", failures[2].Property)
}

func testProviderRead(t *testing.T, provider *Provider, typeName tokens.Type) {
func testProviderRead(t *testing.T, provider *Provider, typeName tokens.Type, checkRawConfig bool) {
urn := resource.NewURN("stack", "project", "", typeName, "name")
props, err := structpb.NewStruct(map[string]interface{}{
"rawConfigValue": "fromRawConfig",
})
require.NoError(t, err)
readResp, err := provider.Read(context.Background(), &pulumirpc.ReadRequest{
Id: string("resource-id"),
Urn: string(urn),
Properties: nil,
Inputs: props,
})
assert.NoError(t, err)
require.NoError(t, err)

assert.NotNil(t, readResp.GetInputs())
assert.NotNil(t, readResp.GetProperties())
Expand Down Expand Up @@ -592,6 +597,19 @@ func testProviderRead(t *testing.T, provider *Provider, typeName tokens.Type) {
assert.Equal(t, resource.NewStringProperty("some ${interpolated:value} with syntax errors"),
ins["stringWithBadInterpolation"])

if checkRawConfig {
readResp, err := provider.Read(context.Background(), &pulumirpc.ReadRequest{
Id: string("set-raw-config-id"),
Urn: string(urn),
Inputs: props,
})
require.NoError(t, err)
outs, err := plugin.UnmarshalProperties(readResp.GetProperties(),
plugin.MarshalOptions{KeepUnknowns: true})
require.NoError(t, err)
assert.Equal(t, "fromRawConfig", outs["stringPropertyValue"].StringValue())
}

// Read again with the ID that results in all the optinal fields not being set
readResp, err = provider.Read(context.Background(), &pulumirpc.ReadRequest{
Id: string("empty-resource-id"),
Expand Down Expand Up @@ -632,7 +650,7 @@ func TestProviderReadV1(t *testing.T) {
},
}

testProviderRead(t, provider, "ExampleResource")
testProviderRead(t, provider, "ExampleResource", false /* CheckRawConfig */)
}

func TestProviderReadV2(t *testing.T) {
Expand All @@ -648,7 +666,7 @@ func TestProviderReadV2(t *testing.T) {
},
}

testProviderRead(t, provider, "ExampleResource")
testProviderRead(t, provider, "ExampleResource", true /* CheckRawConfig */)
}

func testProviderReadNestedSecret(t *testing.T, provider *Provider, typeName tokens.Type) {
Expand Down
10 changes: 5 additions & 5 deletions pkg/tfbridge/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ func TestMetaProperties(t *testing.T) {
res := prov.ResourcesMap().Get(resName)

state := f.NewInstanceState("0")
read, err := prov.Refresh(resName, state)
read, err := prov.Refresh(resName, state, nil)
assert.NoError(t, err)
assert.NotNil(t, read)

Expand All @@ -655,7 +655,7 @@ func TestMetaProperties(t *testing.T) {

assert.Equal(t, strconv.Itoa(res.SchemaVersion()), state.Meta()["schema_version"])

read2, err := prov.Refresh(resName, state)
read2, err := prov.Refresh(resName, state, nil)
assert.NoError(t, err)
assert.NotNil(t, read2)
assert.Equal(t, read, read2)
Expand Down Expand Up @@ -716,7 +716,7 @@ func TestInjectingCustomTimeouts(t *testing.T) {
res := prov.ResourcesMap().Get(resName)

state := f.NewInstanceState("0")
read, err := prov.Refresh(resName, state)
read, err := prov.Refresh(resName, state, nil)
assert.NoError(t, err)
assert.NotNil(t, read)

Expand All @@ -730,7 +730,7 @@ func TestInjectingCustomTimeouts(t *testing.T) {

assert.Equal(t, strconv.Itoa(res.SchemaVersion()), state.Meta()["schema_version"])

read2, err := prov.Refresh(resName, state)
read2, err := prov.Refresh(resName, state, nil)
assert.NoError(t, err)
assert.NotNil(t, read2)
assert.Equal(t, read, read2)
Expand Down Expand Up @@ -821,7 +821,7 @@ func TestResultAttributesRoundTrip(t *testing.T) {
res := prov.ResourcesMap().Get("example_resource")

state := f.NewInstanceState("0")
read, err := prov.Refresh(resName, state)
read, err := prov.Refresh(resName, state, nil)
assert.NoError(t, err)
assert.NotNil(t, read)

Expand Down
2 changes: 1 addition & 1 deletion pkg/tfshim/schema/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func (ProviderShim) Apply(t string, s shim.InstanceState, d shim.InstanceDiff) (
panic("this provider is schema-only and does not support runtime operations")
}

func (ProviderShim) Refresh(t string, s shim.InstanceState) (shim.InstanceState, error) {
func (ProviderShim) Refresh(t string, s shim.InstanceState, c shim.ResourceConfig) (shim.InstanceState, error) {
panic("this provider is schema-only and does not support runtime operations")
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/tfshim/sdk-v1/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func (p v1Provider) Apply(t string, s shim.InstanceState, d shim.InstanceDiff) (
return stateToShim(state), err
}

func (p v1Provider) Refresh(t string, s shim.InstanceState) (shim.InstanceState, error) {
func (p v1Provider) Refresh(t string, s shim.InstanceState, _ shim.ResourceConfig) (shim.InstanceState, error) {
state, err := p.tf.Refresh(instanceInfo(t), stateFromShim(s))
return stateToShim(state), err
}
Expand Down
13 changes: 12 additions & 1 deletion pkg/tfshim/sdk-v2/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,26 @@ func (p v2Provider) Apply(t string, s shim.InstanceState, d shim.InstanceDiff) (
return stateToShim(r, state), errors(diags)
}

func (p v2Provider) Refresh(t string, s shim.InstanceState) (shim.InstanceState, error) {
func (p v2Provider) Refresh(t string, s shim.InstanceState, c shim.ResourceConfig) (shim.InstanceState, error) {
opts, err := getProviderOptions(p.opts)
if err != nil {
return nil, err
}

r, ok := p.tf.ResourcesMap[t]
if !ok {
return nil, fmt.Errorf("unknown resource %v", t)
}

state, err := upgradeResourceState(p.tf, r, stateFromShim(s))
if err != nil {
return nil, fmt.Errorf("failed to upgrade resource state: %w", err)
}

if c != nil {
state.RawConfig = makeResourceRawConfig(opts.diffStrategy, configFromShim(c), r)
}

state, diags := r.RefreshWithoutUpgrade(context.TODO(), state, p.tf.Meta())
return stateToShim(r, state), errors(diags)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/tfshim/shim.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ type Provider interface {
Configure(c ResourceConfig) error
Diff(t string, s InstanceState, c ResourceConfig) (InstanceDiff, error)
Apply(t string, s InstanceState, d InstanceDiff) (InstanceState, error)
Refresh(t string, s InstanceState) (InstanceState, error)
Refresh(t string, s InstanceState, c ResourceConfig) (InstanceState, error)

ReadDataDiff(t string, c ResourceConfig) (InstanceDiff, error)
ReadDataApply(t string, d InstanceDiff) (InstanceState, error)
Expand Down
2 changes: 1 addition & 1 deletion pkg/tfshim/tfplugin5/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ func (p *provider) Apply(t string, s shim.InstanceState, d shim.InstanceDiff) (s
return newState, unmarshalErrors(resp.Diagnostics)
}

func (p *provider) Refresh(t string, s shim.InstanceState) (shim.InstanceState, error) {
func (p *provider) Refresh(t string, s shim.InstanceState, _ shim.ResourceConfig) (shim.InstanceState, error) {
state, ok := s.(*instanceState)
if s != nil && !ok {
return nil, fmt.Errorf("internal error: foreign resource state")
Expand Down
2 changes: 1 addition & 1 deletion pkg/tfshim/tfplugin5/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1294,7 +1294,7 @@ func TestRefresh(t *testing.T) {
"string_with_bad_interpolation": cty.StringVal("some ${interpolated:value} with syntax errors"),
}

state, err = p.Refresh("example_resource", state)
state, err = p.Refresh("example_resource", state, nil)
require.NoError(t, err)

expectedObject, err := ctyToGo(cty.ObjectVal(expected))
Expand Down
4 changes: 2 additions & 2 deletions pkg/tfshim/util/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ func (p *FilteringProvider) Apply(t string, s shim.InstanceState, d shim.Instanc
return p.Provider.Apply(t, s, d)
}

func (p *FilteringProvider) Refresh(t string, s shim.InstanceState) (shim.InstanceState, error) {
return p.Provider.Refresh(t, s)
func (p *FilteringProvider) Refresh(t string, s shim.InstanceState, c shim.ResourceConfig) (shim.InstanceState, error) {
return p.Provider.Refresh(t, s, c)
}

func (p *FilteringProvider) ReadDataDiff(t string, c shim.ResourceConfig) (shim.InstanceDiff, error) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/tfshim/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (UnimplementedProvider) Diff(t string, s shim.InstanceState, c shim.Resourc
func (UnimplementedProvider) Apply(t string, s shim.InstanceState, d shim.InstanceDiff) (shim.InstanceState, error) {
panic("unimplemented")
}
func (UnimplementedProvider) Refresh(t string, s shim.InstanceState) (shim.InstanceState, error) {
func (UnimplementedProvider) Refresh(string, shim.InstanceState, shim.ResourceConfig) (shim.InstanceState, error) {
panic("unimplemented")
}

Expand Down

0 comments on commit 9fb0aa5

Please sign in to comment.