replace testDiffFn and testApplyFn
Replace the old mock provider test functions with modern equivalents. There were a lot of inconsistencies in how they were used, so we needed to update a lot of tests to match the correct behavior.
This commit is contained in:
parent
ca7b5bc28b
commit
0a6853a3f8
File diff suppressed because it is too large
Load Diff
|
@ -30,7 +30,14 @@ func TestContext2Input_provider(t *testing.T) {
|
|||
},
|
||||
},
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
"aws_instance": {},
|
||||
"aws_instance": {
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -98,7 +105,14 @@ func TestContext2Input_providerMulti(t *testing.T) {
|
|||
},
|
||||
},
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
"aws_instance": {},
|
||||
"aws_instance": {
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -159,25 +173,6 @@ func TestContext2Input_providerOnce(t *testing.T) {
|
|||
},
|
||||
})
|
||||
|
||||
//count := 0
|
||||
/*p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
|
||||
count++
|
||||
_, set := c.Config["from_input"]
|
||||
|
||||
if count == 1 {
|
||||
if set {
|
||||
return nil, errors.New("from_input should not be set")
|
||||
}
|
||||
c.Config["from_input"] = "x"
|
||||
}
|
||||
|
||||
if count > 1 && !set {
|
||||
return nil, errors.New("from_input should be set")
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}*/
|
||||
|
||||
if diags := ctx.Input(InputModeStd); diags.HasErrors() {
|
||||
t.Fatalf("input errors: %s", diags.Err())
|
||||
}
|
||||
|
@ -202,7 +197,14 @@ func TestContext2Input_providerId(t *testing.T) {
|
|||
},
|
||||
},
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
"aws_instance": {},
|
||||
"aws_instance": {
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -726,6 +726,7 @@ func TestContext2Refresh_output(t *testing.T) {
|
|||
"foo": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -5,16 +5,13 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/hashicorp/go-version"
|
||||
|
@ -22,7 +19,6 @@ import (
|
|||
"github.com/hashicorp/terraform/configs/configload"
|
||||
"github.com/hashicorp/terraform/configs/configschema"
|
||||
"github.com/hashicorp/terraform/configs/hcl2shim"
|
||||
"github.com/hashicorp/terraform/flatmap"
|
||||
"github.com/hashicorp/terraform/plans"
|
||||
"github.com/hashicorp/terraform/plans/planfile"
|
||||
"github.com/hashicorp/terraform/providers"
|
||||
|
@ -132,300 +128,98 @@ func testContext2(t *testing.T, opts *ContextOpts) *Context {
|
|||
return ctx
|
||||
}
|
||||
|
||||
func testDataApplyFn(
|
||||
info *InstanceInfo,
|
||||
d *InstanceDiff) (*InstanceState, error) {
|
||||
return testApplyFn(info, new(InstanceState), d)
|
||||
}
|
||||
|
||||
func testDataDiffFn(
|
||||
info *InstanceInfo,
|
||||
c *ResourceConfig) (*InstanceDiff, error) {
|
||||
return testDiffFn(info, new(InstanceState), c)
|
||||
}
|
||||
|
||||
func testApplyFn(
|
||||
info *InstanceInfo,
|
||||
s *InstanceState,
|
||||
d *InstanceDiff) (*InstanceState, error) {
|
||||
if d.Destroy {
|
||||
return nil, nil
|
||||
func testApplyFn(req providers.ApplyResourceChangeRequest) (resp providers.ApplyResourceChangeResponse) {
|
||||
resp.NewState = req.PlannedState
|
||||
if req.PlannedState.IsNull() {
|
||||
resp.NewState = cty.NullVal(req.PriorState.Type())
|
||||
return
|
||||
}
|
||||
|
||||
// find the OLD id, which is probably in the ID field for now, but eventually
|
||||
// ID should only be in one place.
|
||||
id := s.ID
|
||||
if id == "" {
|
||||
id = s.Attributes["id"]
|
||||
}
|
||||
if idAttr, ok := d.Attributes["id"]; ok && !idAttr.NewComputed {
|
||||
id = idAttr.New
|
||||
planned := req.PlannedState.AsValueMap()
|
||||
if planned == nil {
|
||||
planned = map[string]cty.Value{}
|
||||
}
|
||||
|
||||
if id == "" || id == hcl2shim.UnknownVariableValue {
|
||||
id = "foo"
|
||||
id, ok := planned["id"]
|
||||
if !ok || id.IsNull() || !id.IsKnown() {
|
||||
planned["id"] = cty.StringVal("foo")
|
||||
}
|
||||
|
||||
result := &InstanceState{
|
||||
ID: id,
|
||||
Attributes: make(map[string]string),
|
||||
// our default schema has a computed "type" attr
|
||||
if ty, ok := planned["type"]; ok && !ty.IsNull() {
|
||||
planned["type"] = cty.StringVal(req.TypeName)
|
||||
}
|
||||
|
||||
// Copy all the prior attributes
|
||||
for k, v := range s.Attributes {
|
||||
result.Attributes[k] = v
|
||||
if cmp, ok := planned["compute"]; ok && !cmp.IsNull() {
|
||||
computed := cmp.AsString()
|
||||
if val, ok := planned[computed]; ok && !val.IsKnown() {
|
||||
planned[computed] = cty.StringVal("computed_value")
|
||||
}
|
||||
}
|
||||
|
||||
if d != nil {
|
||||
result = result.MergeDiff(d)
|
||||
for k, v := range planned {
|
||||
if k == "unknown" {
|
||||
// "unknown" should cause an error
|
||||
continue
|
||||
}
|
||||
|
||||
// The id attribute always matches ID for the sake of this mock
|
||||
// implementation, since it's following the pre-0.12 assumptions where
|
||||
// these two were treated as synonyms.
|
||||
result.Attributes["id"] = result.ID
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func testDiffFn(
|
||||
info *InstanceInfo,
|
||||
s *InstanceState,
|
||||
c *ResourceConfig) (*InstanceDiff, error) {
|
||||
diff := new(InstanceDiff)
|
||||
diff.Attributes = make(map[string]*ResourceAttrDiff)
|
||||
|
||||
defer func() {
|
||||
log.Printf("[TRACE] testDiffFn: generated diff is:\n%s", spew.Sdump(diff))
|
||||
}()
|
||||
|
||||
if s != nil {
|
||||
diff.DestroyTainted = s.Tainted
|
||||
}
|
||||
|
||||
for k, v := range c.Raw {
|
||||
// Ignore __-prefixed keys since they're used for magic
|
||||
if k[0] == '_' && k[1] == '_' {
|
||||
// ...though we do still need to include them in the diff, to
|
||||
// simulate normal provider behaviors.
|
||||
old := s.Attributes[k]
|
||||
var new string
|
||||
switch tv := v.(type) {
|
||||
case string:
|
||||
new = tv
|
||||
if !v.IsKnown() {
|
||||
switch k {
|
||||
case "type":
|
||||
planned[k] = cty.StringVal(req.TypeName)
|
||||
default:
|
||||
new = fmt.Sprintf("%#v", v)
|
||||
}
|
||||
if new == hcl2shim.UnknownVariableValue {
|
||||
diff.Attributes[k] = &ResourceAttrDiff{
|
||||
Old: old,
|
||||
New: "",
|
||||
NewComputed: true,
|
||||
}
|
||||
} else {
|
||||
diff.Attributes[k] = &ResourceAttrDiff{
|
||||
Old: old,
|
||||
New: new,
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if k == "nil" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// This key is used for other purposes
|
||||
if k == "compute_value" {
|
||||
if old, ok := s.Attributes["compute_value"]; !ok || old != v.(string) {
|
||||
diff.Attributes["compute_value"] = &ResourceAttrDiff{
|
||||
Old: old,
|
||||
New: v.(string),
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if k == "compute" {
|
||||
// The "compute" value itself must be included in the diff if it
|
||||
// has changed since prior.
|
||||
if old, ok := s.Attributes["compute"]; !ok || old != v.(string) {
|
||||
diff.Attributes["compute"] = &ResourceAttrDiff{
|
||||
Old: old,
|
||||
New: v.(string),
|
||||
}
|
||||
}
|
||||
|
||||
if v == hcl2shim.UnknownVariableValue || v == "unknown" {
|
||||
// compute wasn't set in the config, so don't use these
|
||||
// computed values from the schema.
|
||||
delete(c.Raw, k)
|
||||
delete(c.Raw, "compute_value")
|
||||
|
||||
// we need to remove this from the list of ComputedKeys too,
|
||||
// since it would get re-added to the diff further down
|
||||
newComputed := make([]string, 0, len(c.ComputedKeys))
|
||||
for _, ck := range c.ComputedKeys {
|
||||
if ck == "compute" || ck == "compute_value" {
|
||||
continue
|
||||
}
|
||||
newComputed = append(newComputed, ck)
|
||||
}
|
||||
c.ComputedKeys = newComputed
|
||||
|
||||
if v == "unknown" {
|
||||
diff.Attributes["unknown"] = &ResourceAttrDiff{
|
||||
Old: "",
|
||||
New: "",
|
||||
NewComputed: true,
|
||||
}
|
||||
|
||||
c.ComputedKeys = append(c.ComputedKeys, "unknown")
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
attrDiff := &ResourceAttrDiff{
|
||||
Old: "",
|
||||
New: "",
|
||||
NewComputed: true,
|
||||
}
|
||||
|
||||
if cv, ok := c.Config["compute_value"]; ok {
|
||||
if cv.(string) == "1" {
|
||||
attrDiff.NewComputed = false
|
||||
attrDiff.New = fmt.Sprintf("computed_%s", v.(string))
|
||||
}
|
||||
}
|
||||
|
||||
diff.Attributes[v.(string)] = attrDiff
|
||||
continue
|
||||
}
|
||||
|
||||
// If this key is not computed, then look it up in the
|
||||
// cleaned config.
|
||||
found := false
|
||||
for _, ck := range c.ComputedKeys {
|
||||
if ck == k {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
v = c.Config[k]
|
||||
}
|
||||
|
||||
for k, attrDiff := range testFlatAttrDiffs(k, v) {
|
||||
// we need to ignore 'id' for now, since it's always inferred to be
|
||||
// computed.
|
||||
if k == "id" {
|
||||
continue
|
||||
}
|
||||
|
||||
if k == "require_new" {
|
||||
attrDiff.RequiresNew = true
|
||||
}
|
||||
if _, ok := c.Raw["__"+k+"_requires_new"]; ok {
|
||||
attrDiff.RequiresNew = true
|
||||
}
|
||||
|
||||
if attr, ok := s.Attributes[k]; ok {
|
||||
attrDiff.Old = attr
|
||||
}
|
||||
|
||||
diff.Attributes[k] = attrDiff
|
||||
}
|
||||
}
|
||||
|
||||
for _, k := range c.ComputedKeys {
|
||||
if k == "id" {
|
||||
continue
|
||||
}
|
||||
old := ""
|
||||
if s != nil {
|
||||
old = s.Attributes[k]
|
||||
}
|
||||
diff.Attributes[k] = &ResourceAttrDiff{
|
||||
Old: old,
|
||||
NewComputed: true,
|
||||
}
|
||||
}
|
||||
|
||||
// If we recreate this resource because it's tainted, we keep all attrs
|
||||
if !diff.RequiresNew() {
|
||||
for k, v := range diff.Attributes {
|
||||
if v.NewComputed {
|
||||
continue
|
||||
}
|
||||
|
||||
old, ok := s.Attributes[k]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if old == v.New {
|
||||
delete(diff.Attributes, k)
|
||||
planned[k] = cty.NullVal(v.Type())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !diff.Empty() {
|
||||
diff.Attributes["type"] = &ResourceAttrDiff{
|
||||
Old: "",
|
||||
New: info.Type,
|
||||
}
|
||||
if s != nil && s.Attributes != nil {
|
||||
diff.Attributes["type"].Old = s.Attributes["type"]
|
||||
}
|
||||
}
|
||||
|
||||
return diff, nil
|
||||
resp.NewState = cty.ObjectVal(planned)
|
||||
return
|
||||
}
|
||||
|
||||
// generate ResourceAttrDiffs for nested data structures in tests
|
||||
func testFlatAttrDiffs(k string, i interface{}) map[string]*ResourceAttrDiff {
|
||||
diffs := make(map[string]*ResourceAttrDiff)
|
||||
// check for strings and empty containers first
|
||||
switch t := i.(type) {
|
||||
case string:
|
||||
diffs[k] = &ResourceAttrDiff{New: t}
|
||||
return diffs
|
||||
case map[string]interface{}:
|
||||
if len(t) == 0 {
|
||||
diffs[k] = &ResourceAttrDiff{New: ""}
|
||||
return diffs
|
||||
func testDiffFn(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
|
||||
var planned map[string]cty.Value
|
||||
if !req.ProposedNewState.IsNull() {
|
||||
planned = req.ProposedNewState.AsValueMap()
|
||||
}
|
||||
case []interface{}:
|
||||
if len(t) == 0 {
|
||||
diffs[k] = &ResourceAttrDiff{New: ""}
|
||||
return diffs
|
||||
if planned == nil {
|
||||
planned = map[string]cty.Value{}
|
||||
}
|
||||
|
||||
// id is always computed for the tests
|
||||
if id, ok := planned["id"]; ok && id.IsNull() {
|
||||
planned["id"] = cty.UnknownVal(cty.String)
|
||||
}
|
||||
|
||||
// the old tests have require_new replace on every plan
|
||||
if _, ok := planned["require_new"]; ok {
|
||||
resp.RequiresReplace = append(resp.RequiresReplace, cty.Path{cty.GetAttrStep{Name: "require_new"}})
|
||||
}
|
||||
|
||||
for k := range planned {
|
||||
requiresNewKey := "__" + k + "_requires_new"
|
||||
_, ok := planned[requiresNewKey]
|
||||
if ok {
|
||||
resp.RequiresReplace = append(resp.RequiresReplace, cty.Path{cty.GetAttrStep{Name: requiresNewKey}})
|
||||
}
|
||||
}
|
||||
|
||||
flat := flatmap.Flatten(map[string]interface{}{k: i})
|
||||
|
||||
for k, v := range flat {
|
||||
attrDiff := &ResourceAttrDiff{
|
||||
Old: "",
|
||||
New: v,
|
||||
if v, ok := planned["compute"]; ok && !v.IsNull() {
|
||||
k := v.AsString()
|
||||
unknown := cty.UnknownVal(cty.String)
|
||||
if strings.HasSuffix(k, ".#") {
|
||||
k = k[:len(k)-2]
|
||||
unknown = cty.UnknownVal(cty.List(cty.String))
|
||||
}
|
||||
diffs[k] = attrDiff
|
||||
planned[k] = unknown
|
||||
}
|
||||
|
||||
// The legacy flatmap-based diff producing done by helper/schema would
|
||||
// additionally insert a k+".%" key here recording the length of the map,
|
||||
// which is for some reason not also done by flatmap.Flatten. To make our
|
||||
// mock shims helper/schema-compatible, we'll just fake that up here.
|
||||
switch t := i.(type) {
|
||||
case map[string]interface{}:
|
||||
attrDiff := &ResourceAttrDiff{
|
||||
Old: "",
|
||||
New: strconv.Itoa(len(t)),
|
||||
}
|
||||
diffs[k+".%"] = attrDiff
|
||||
if t, ok := planned["type"]; ok && t.IsNull() {
|
||||
planned["type"] = cty.UnknownVal(cty.String)
|
||||
}
|
||||
|
||||
return diffs
|
||||
resp.PlannedState = cty.ObjectVal(planned)
|
||||
return
|
||||
}
|
||||
|
||||
func testProvider(prefix string) *MockProvider {
|
||||
|
|
|
@ -2,7 +2,6 @@ package terraform
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
|
@ -89,14 +88,12 @@ type MockProvider struct {
|
|||
CloseCalled bool
|
||||
CloseError error
|
||||
|
||||
// Legacy callbacks: if these are set, we will shim incoming calls for
|
||||
// new-style methods to these old-fashioned terraform.ResourceProvider
|
||||
// mock callbacks, for the benefit of older tests that were written against
|
||||
// the old mock API.
|
||||
ValidateFn func(c *ResourceConfig) (ws []string, es []error)
|
||||
ConfigureFn func(c *ResourceConfig) error
|
||||
DiffFn func(info *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error)
|
||||
ApplyFn func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error)
|
||||
//ValidateFn func(providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse
|
||||
//ConfigureFn func(providers.ConfigureRequest) providers.ConfigureResponse
|
||||
DiffFn func(providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse
|
||||
ApplyFn func(providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse
|
||||
}
|
||||
|
||||
func (p *MockProvider) GetSchema() providers.GetSchemaResponse {
|
||||
|
@ -297,47 +294,7 @@ func (p *MockProvider) PlanResourceChange(r providers.PlanResourceChangeRequest)
|
|||
p.PlanResourceChangeRequest = r
|
||||
|
||||
if p.DiffFn != nil {
|
||||
ps := p.getSchema()
|
||||
if ps.ResourceTypes == nil || ps.ResourceTypes[r.TypeName].Block == nil {
|
||||
return providers.PlanResourceChangeResponse{
|
||||
Diagnostics: tfdiags.Diagnostics(nil).Append(fmt.Printf("mock provider has no schema for resource type %s", r.TypeName)),
|
||||
}
|
||||
}
|
||||
schema := ps.ResourceTypes[r.TypeName].Block
|
||||
info := &InstanceInfo{
|
||||
Type: r.TypeName,
|
||||
}
|
||||
priorState := NewInstanceStateShimmedFromValue(r.PriorState, 0)
|
||||
cfg := NewResourceConfigShimmed(r.ProposedNewState, schema)
|
||||
|
||||
legacyDiff, err := p.DiffFn(info, priorState, cfg)
|
||||
|
||||
var res providers.PlanResourceChangeResponse
|
||||
res.PlannedState = r.ProposedNewState
|
||||
if err != nil {
|
||||
res.Diagnostics = res.Diagnostics.Append(err)
|
||||
}
|
||||
if legacyDiff != nil {
|
||||
newVal, err := legacyDiff.ApplyToValue(r.PriorState, schema)
|
||||
if err != nil {
|
||||
res.Diagnostics = res.Diagnostics.Append(err)
|
||||
}
|
||||
|
||||
res.PlannedState = newVal
|
||||
|
||||
var requiresNew []string
|
||||
for attr, d := range legacyDiff.Attributes {
|
||||
if d.RequiresNew {
|
||||
requiresNew = append(requiresNew, attr)
|
||||
}
|
||||
}
|
||||
requiresReplace, err := hcl2shim.RequiresReplace(requiresNew, schema.ImpliedType())
|
||||
if err != nil {
|
||||
res.Diagnostics = res.Diagnostics.Append(err)
|
||||
}
|
||||
res.RequiresReplace = requiresReplace
|
||||
}
|
||||
return res
|
||||
return p.DiffFn(r)
|
||||
}
|
||||
if p.PlanResourceChangeFn != nil {
|
||||
return p.PlanResourceChangeFn(r)
|
||||
|
@ -353,90 +310,7 @@ func (p *MockProvider) ApplyResourceChange(r providers.ApplyResourceChangeReques
|
|||
p.Unlock()
|
||||
|
||||
if p.ApplyFn != nil {
|
||||
// ApplyFn is a special callback fashioned after our old provider
|
||||
// interface, which expected to be given an actual diff rather than
|
||||
// separate old/new values to apply. Therefore we need to approximate
|
||||
// a diff here well enough that _most_ of our legacy ApplyFns in old
|
||||
// tests still see the behavior they are expecting. New tests should
|
||||
// not use this, and should instead use ApplyResourceChangeFn directly.
|
||||
providerSchema := p.getSchema()
|
||||
schema, ok := providerSchema.ResourceTypes[r.TypeName]
|
||||
if !ok {
|
||||
return providers.ApplyResourceChangeResponse{
|
||||
Diagnostics: tfdiags.Diagnostics(nil).Append(fmt.Errorf("no mocked schema available for resource type %s", r.TypeName)),
|
||||
}
|
||||
}
|
||||
|
||||
info := &InstanceInfo{
|
||||
Type: r.TypeName,
|
||||
}
|
||||
|
||||
priorVal := r.PriorState
|
||||
plannedVal := r.PlannedState
|
||||
priorMap := hcl2shim.FlatmapValueFromHCL2(priorVal)
|
||||
plannedMap := hcl2shim.FlatmapValueFromHCL2(plannedVal)
|
||||
s := NewInstanceStateShimmedFromValue(priorVal, 0)
|
||||
d := &InstanceDiff{
|
||||
Attributes: make(map[string]*ResourceAttrDiff),
|
||||
}
|
||||
if plannedMap == nil { // destroying, then
|
||||
d.Destroy = true
|
||||
// Destroy diffs don't have any attribute diffs
|
||||
} else {
|
||||
if priorMap == nil { // creating, then
|
||||
// We'll just make an empty prior map to make things easier below.
|
||||
priorMap = make(map[string]string)
|
||||
}
|
||||
|
||||
for k, new := range plannedMap {
|
||||
old := priorMap[k]
|
||||
newComputed := false
|
||||
if new == hcl2shim.UnknownVariableValue {
|
||||
new = ""
|
||||
newComputed = true
|
||||
}
|
||||
d.Attributes[k] = &ResourceAttrDiff{
|
||||
Old: old,
|
||||
New: new,
|
||||
NewComputed: newComputed,
|
||||
Type: DiffAttrInput, // not generally used in tests, so just hard-coded
|
||||
}
|
||||
}
|
||||
// Also need any attributes that were removed in "planned"
|
||||
for k, old := range priorMap {
|
||||
if _, ok := plannedMap[k]; ok {
|
||||
continue
|
||||
}
|
||||
d.Attributes[k] = &ResourceAttrDiff{
|
||||
Old: old,
|
||||
NewRemoved: true,
|
||||
Type: DiffAttrInput,
|
||||
}
|
||||
}
|
||||
}
|
||||
newState, err := p.ApplyFn(info, s, d)
|
||||
resp := providers.ApplyResourceChangeResponse{}
|
||||
if err != nil {
|
||||
resp.Diagnostics = resp.Diagnostics.Append(err)
|
||||
}
|
||||
if newState != nil {
|
||||
var newVal cty.Value
|
||||
if newState != nil {
|
||||
var err error
|
||||
newVal, err = newState.AttrsAsObjectValue(schema.Block.ImpliedType())
|
||||
if err != nil {
|
||||
resp.Diagnostics = resp.Diagnostics.Append(err)
|
||||
}
|
||||
} else {
|
||||
// If apply returned a nil new state then that's the old way to
|
||||
// indicate that the object was destroyed. Our new interface calls
|
||||
// for that to be signalled as a null value.
|
||||
newVal = cty.NullVal(schema.Block.ImpliedType())
|
||||
}
|
||||
resp.NewState = newVal
|
||||
}
|
||||
|
||||
return resp
|
||||
return p.ApplyFn(r)
|
||||
}
|
||||
if p.ApplyResourceChangeFn != nil {
|
||||
return p.ApplyResourceChangeFn(r)
|
||||
|
|
|
@ -414,12 +414,15 @@ aws_instance.bar:
|
|||
aws_instance.foo.0:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
aws_instance.foo.1:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
aws_instance.foo.2:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
`
|
||||
|
||||
const testTerraformApplyProviderAliasStr = `
|
||||
|
@ -439,9 +442,11 @@ const testTerraformApplyProviderAliasConfigStr = `
|
|||
another_instance.bar:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/another"].two
|
||||
type = another_instance
|
||||
another_instance.foo:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/another"]
|
||||
type = another_instance
|
||||
`
|
||||
|
||||
const testTerraformApplyEmptyModuleStr = `
|
||||
|
@ -487,6 +492,7 @@ const testTerraformApplyCancelStr = `
|
|||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
value = 2
|
||||
`
|
||||
|
||||
|
@ -590,9 +596,11 @@ aws_instance.bar:
|
|||
aws_instance.foo.0:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
aws_instance.foo.1:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
`
|
||||
const testTerraformApplyForEachVariableStr = `
|
||||
aws_instance.foo["b15c6d616d6143248c575900dff57325eb1de498"]:
|
||||
|
@ -613,18 +621,22 @@ aws_instance.foo["e30a7edcc42a846684f2a4eea5f3cd261d33c46d"]:
|
|||
aws_instance.one["a"]:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
aws_instance.one["b"]:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
aws_instance.two["a"]:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
|
||||
Dependencies:
|
||||
aws_instance.one
|
||||
aws_instance.two["b"]:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
|
||||
Dependencies:
|
||||
aws_instance.one`
|
||||
|
@ -632,9 +644,11 @@ const testTerraformApplyMinimalStr = `
|
|||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
`
|
||||
|
||||
const testTerraformApplyModuleStr = `
|
||||
|
@ -688,9 +702,11 @@ module.child:
|
|||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
test_instance.foo:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/test"]
|
||||
type = test_instance
|
||||
`
|
||||
|
||||
const testTerraformApplyModuleProviderAliasStr = `
|
||||
|
@ -699,6 +715,7 @@ module.child:
|
|||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = module.child.provider["registry.terraform.io/hashicorp/aws"].eu
|
||||
type = aws_instance
|
||||
`
|
||||
|
||||
const testTerraformApplyModuleVarRefExistingStr = `
|
||||
|
@ -706,6 +723,7 @@ aws_instance.foo:
|
|||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
foo = bar
|
||||
type = aws_instance
|
||||
|
||||
module.child:
|
||||
aws_instance.foo:
|
||||
|
@ -733,6 +751,7 @@ const testTerraformApplyProvisionerStr = `
|
|||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
|
||||
Dependencies:
|
||||
aws_instance.foo
|
||||
|
@ -752,12 +771,14 @@ module.child:
|
|||
aws_instance.bar:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
`
|
||||
|
||||
const testTerraformApplyProvisionerFailStr = `
|
||||
aws_instance.bar: (tainted)
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
|
@ -769,6 +790,7 @@ const testTerraformApplyProvisionerFailCreateStr = `
|
|||
aws_instance.bar: (tainted)
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
`
|
||||
|
||||
const testTerraformApplyProvisionerFailCreateNoIdStr = `
|
||||
|
@ -850,14 +872,16 @@ const testTerraformApplyDestroyStr = `
|
|||
|
||||
const testTerraformApplyErrorStr = `
|
||||
aws_instance.bar: (tainted)
|
||||
ID = bar
|
||||
ID =
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
foo = 2
|
||||
|
||||
Dependencies:
|
||||
aws_instance.foo
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
value = 2
|
||||
`
|
||||
|
||||
|
@ -866,6 +890,7 @@ aws_instance.bar:
|
|||
ID = bar
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
require_new = abc
|
||||
type = aws_instance
|
||||
`
|
||||
|
||||
const testTerraformApplyErrorDestroyCreateBeforeDestroyStr = `
|
||||
|
@ -881,12 +906,14 @@ const testTerraformApplyErrorPartialStr = `
|
|||
aws_instance.bar:
|
||||
ID = bar
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
|
||||
Dependencies:
|
||||
aws_instance.foo
|
||||
aws_instance.foo:
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
type = aws_instance
|
||||
value = 2
|
||||
`
|
||||
|
||||
|
@ -1107,7 +1134,6 @@ const testTerraformApplyUnknownAttrStr = `
|
|||
aws_instance.foo: (tainted)
|
||||
ID = foo
|
||||
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||
compute = unknown
|
||||
num = 2
|
||||
type = aws_instance
|
||||
`
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
variable "require_new" {
|
||||
type = string
|
||||
}
|
||||
|
||||
resource "aws_instance" "web" {
|
||||
// require_new is a special attribute recognized by testDiffFn that forces
|
||||
// a new resource on every apply
|
||||
require_new = "yes"
|
||||
require_new = var.require_new
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
resource "aws_instance" "foo" {
|
||||
num = "2"
|
||||
compute = "unknown"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue