Merge pull request #26519 from hashicorp/jbardin/FIXME

Cleanup and remove legacy types from test mocks
This commit is contained in:
James Bardin 2020-10-08 14:54:40 -04:00 committed by GitHub
commit 57a47d0b82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 1366 additions and 2160 deletions

View File

@ -478,12 +478,6 @@ Plan: 1 to add, 0 to change, 1 to destroy.`
}
func TestLocal_planRefreshFalse(t *testing.T) {
// since there is no longer a separate Refresh walk, `-refresh=false
// doesn't do anything.
// FIXME: determine if we need a refresh option for the new plan, or remove
// this test
t.Skip()
b, cleanup := TestLocal(t)
defer cleanup()

View File

@ -79,12 +79,13 @@ func TestLocal_refreshInput(t *testing.T) {
p.ReadResourceResponse = providers.ReadResourceResponse{NewState: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("yes"),
})}
p.ConfigureFn = func(c *terraform.ResourceConfig) error {
if v, ok := c.Get("value"); !ok || v != "bar" {
return fmt.Errorf("no value set")
p.ConfigureFn = func(req providers.ConfigureRequest) (resp providers.ConfigureResponse) {
val := req.Config.GetAttr("value")
if val.IsNull() || val.AsString() != "bar" {
resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("incorrect value %#v", val))
}
return nil
return
}
// Enable input asking since it is normally disabled by default

View File

@ -341,43 +341,26 @@ func TestApply_error(t *testing.T) {
var lock sync.Mutex
errored := false
p.ApplyFn = func(info *terraform.InstanceInfo, s *terraform.InstanceState, d *terraform.InstanceDiff) (*terraform.InstanceState, error) {
p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) (resp providers.ApplyResourceChangeResponse) {
lock.Lock()
defer lock.Unlock()
if !errored {
errored = true
return nil, fmt.Errorf("error")
resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("error"))
}
newState := &terraform.InstanceState{
ID: "foo",
Attributes: map[string]string{},
}
newState.Attributes["id"] = newState.ID
if ad, ok := d.Attributes["ami"]; ok {
newState.Attributes["ami"] = ad.New
}
if ad, ok := d.Attributes["error"]; ok {
newState.Attributes["error"] = ad.New
}
return newState, nil
s := req.PlannedState.AsValueMap()
s["id"] = cty.StringVal("foo")
resp.NewState = cty.ObjectVal(s)
return
}
p.DiffFn = func(info *terraform.InstanceInfo, s *terraform.InstanceState, rc *terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
ret := &terraform.InstanceDiff{
Attributes: map[string]*terraform.ResourceAttrDiff{},
}
if new, ok := rc.Get("ami"); ok {
ret.Attributes["ami"] = &terraform.ResourceAttrDiff{
New: new.(string),
}
}
if new, ok := rc.Get("error"); ok {
ret.Attributes["error"] = &terraform.ResourceAttrDiff{
New: fmt.Sprintf("%t", new.(bool)),
}
}
return ret, nil
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
s := req.ProposedNewState.AsValueMap()
s["id"] = cty.UnknownVal(cty.String)
resp.PlannedState = cty.ObjectVal(s)
return
}
p.GetSchemaReturn = &terraform.ProviderSchema{
ResourceTypes: map[string]*configschema.Block{
@ -902,25 +885,13 @@ func TestApply_shutdown(t *testing.T) {
return nil
}
p.DiffFn = func(
*terraform.InstanceInfo,
*terraform.InstanceState,
*terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
return &terraform.InstanceDiff{
Attributes: map[string]*terraform.ResourceAttrDiff{
"ami": &terraform.ResourceAttrDiff{
New: "bar",
},
},
}, nil
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
resp.PlannedState = req.ProposedNewState
return
}
var once sync.Once
p.ApplyFn = func(
*terraform.InstanceInfo,
*terraform.InstanceState,
*terraform.InstanceDiff) (*terraform.InstanceState, error) {
p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) (resp providers.ApplyResourceChangeResponse) {
// only cancel once
once.Do(func() {
shutdownCh <- struct{}{}
@ -934,12 +905,8 @@ func TestApply_shutdown(t *testing.T) {
// canceled.
time.Sleep(200 * time.Millisecond)
return &terraform.InstanceState{
ID: "foo",
Attributes: map[string]string{
"ami": "2",
},
}, nil
resp.NewState = req.PlannedState
return
}
p.GetSchemaReturn = &terraform.ProviderSchema{

View File

@ -110,7 +110,7 @@ func TestImport_providerConfig(t *testing.T) {
}
configured := false
p.ConfigureNewFn = func(req providers.ConfigureRequest) providers.ConfigureResponse {
p.ConfigureFn = func(req providers.ConfigureRequest) providers.ConfigureResponse {
configured = true
cfg := req.Config
@ -217,7 +217,7 @@ func TestImport_remoteState(t *testing.T) {
}
configured := false
p.ConfigureNewFn = func(req providers.ConfigureRequest) providers.ConfigureResponse {
p.ConfigureFn = func(req providers.ConfigureRequest) providers.ConfigureResponse {
var diags tfdiags.Diagnostics
configured = true
if got, want := req.Config.GetAttr("foo"), cty.StringVal("bar"); !want.RawEquals(got) {
@ -364,7 +364,7 @@ func TestImport_providerConfigWithVar(t *testing.T) {
}
configured := false
p.ConfigureNewFn = func(req providers.ConfigureRequest) providers.ConfigureResponse {
p.ConfigureFn = func(req providers.ConfigureRequest) providers.ConfigureResponse {
var diags tfdiags.Diagnostics
configured = true
if got, want := req.Config.GetAttr("foo"), cty.StringVal("bar"); !want.RawEquals(got) {
@ -495,7 +495,7 @@ func TestImport_providerConfigWithVarDefault(t *testing.T) {
}
configured := false
p.ConfigureNewFn = func(req providers.ConfigureRequest) providers.ConfigureResponse {
p.ConfigureFn = func(req providers.ConfigureRequest) providers.ConfigureResponse {
var diags tfdiags.Diagnostics
configured = true
if got, want := req.Config.GetAttr("foo"), cty.StringVal("bar"); !want.RawEquals(got) {
@ -568,7 +568,7 @@ func TestImport_providerConfigWithVarFile(t *testing.T) {
}
configured := false
p.ConfigureNewFn = func(req providers.ConfigureRequest) providers.ConfigureResponse {
p.ConfigureFn = func(req providers.ConfigureRequest) providers.ConfigureResponse {
var diags tfdiags.Diagnostics
configured = true
if got, want := req.Config.GetAttr("foo"), cty.StringVal("bar"); !want.RawEquals(got) {

View File

@ -523,15 +523,10 @@ func TestPlan_vars(t *testing.T) {
}
actual := ""
p.DiffFn = func(
info *terraform.InstanceInfo,
s *terraform.InstanceState,
c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
if v, ok := c.Config["value"]; ok {
actual = v.(string)
}
return nil, nil
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
actual = req.ProposedNewState.GetAttr("value").AsString()
resp.PlannedState = req.ProposedNewState
return
}
args := []string{
@ -655,15 +650,10 @@ func TestPlan_varFile(t *testing.T) {
}
actual := ""
p.DiffFn = func(
info *terraform.InstanceInfo,
s *terraform.InstanceState,
c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
if v, ok := c.Config["value"]; ok {
actual = v.(string)
}
return nil, nil
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
actual = req.ProposedNewState.GetAttr("value").AsString()
resp.PlannedState = req.ProposedNewState
return
}
args := []string{
@ -705,15 +695,10 @@ func TestPlan_varFileDefault(t *testing.T) {
}
actual := ""
p.DiffFn = func(
info *terraform.InstanceInfo,
s *terraform.InstanceState,
c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
if v, ok := c.Config["value"]; ok {
actual = v.(string)
}
return nil, nil
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
actual = req.ProposedNewState.GetAttr("value").AsString()
resp.PlannedState = req.ProposedNewState
return
}
args := []string{
@ -823,11 +808,7 @@ func TestPlan_shutdown(t *testing.T) {
var once sync.Once
p.DiffFn = func(
*terraform.InstanceInfo,
*terraform.InstanceState,
*terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
once.Do(func() {
shutdownCh <- struct{}{}
})
@ -840,14 +821,12 @@ func TestPlan_shutdown(t *testing.T) {
// canceled.
time.Sleep(200 * time.Millisecond)
return &terraform.InstanceDiff{
Attributes: map[string]*terraform.ResourceAttrDiff{
"ami": &terraform.ResourceAttrDiff{
New: "bar",
},
},
}, nil
s := req.ProposedNewState.AsValueMap()
s["ami"] = cty.StringVal("bar")
resp.PlannedState = cty.ObjectVal(s)
return
}
p.GetSchemaReturn = &terraform.ProviderSchema{
ResourceTypes: map[string]*configschema.Block{
"test_instance": {

File diff suppressed because it is too large Load Diff

View File

@ -48,8 +48,8 @@ func contextFixtureApplyVars(t *testing.T) *contextTestFixture {
"map": {Type: cty.Map(cty.String), Optional: true},
},
})
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
return &contextTestFixture{
Config: c,
Providers: map[addrs.Provider]providers.Factory{
@ -74,8 +74,8 @@ func contextFixtureApplyVarsEnv(t *testing.T) *contextTestFixture {
"type": {Type: cty.String, Computed: true},
},
})
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
return &contextTestFixture{
Config: c,
Providers: map[addrs.Provider]providers.Factory{

View File

@ -1,7 +1,7 @@
package terraform
import (
"fmt"
"errors"
"strings"
"testing"
@ -196,15 +196,13 @@ func TestContextImport_moduleProvider(t *testing.T) {
},
}
configured := false
p.ConfigureFn = func(c *ResourceConfig) error {
configured = true
if v, ok := c.Get("foo"); !ok || v.(string) != "bar" {
return fmt.Errorf("bad")
p.ConfigureFn = func(req providers.ConfigureRequest) (resp providers.ConfigureResponse) {
foo := req.Config.GetAttr("foo").AsString()
if foo != "bar" {
resp.Diagnostics = resp.Diagnostics.Append(errors.New("not bar"))
}
return nil
return
}
m := testModule(t, "import-provider")
@ -229,7 +227,7 @@ func TestContextImport_moduleProvider(t *testing.T) {
t.Fatalf("unexpected errors: %s", diags.Err())
}
if !configured {
if !p.ConfigureCalled {
t.Fatal("didn't configure provider")
}
@ -258,15 +256,13 @@ func TestContextImport_providerModule(t *testing.T) {
},
}
configured := false
p.ConfigureFn = func(c *ResourceConfig) error {
configured = true
if v, ok := c.Get("foo"); !ok || v.(string) != "bar" {
return fmt.Errorf("bad")
p.ConfigureFn = func(req providers.ConfigureRequest) (resp providers.ConfigureResponse) {
foo := req.Config.GetAttr("foo").AsString()
if foo != "bar" {
resp.Diagnostics = resp.Diagnostics.Append(errors.New("not bar"))
}
return nil
return
}
_, diags := ctx.Import(&ImportOpts{
@ -283,7 +279,7 @@ func TestContextImport_providerModule(t *testing.T) {
t.Fatalf("unexpected errors: %s", diags.Err())
}
if !configured {
if !p.ConfigureCalled {
t.Fatal("didn't configure provider")
}
}

View File

@ -17,8 +17,8 @@ import (
func TestContext2Input_provider(t *testing.T) {
m := testModule(t, "input-provider")
p := testProvider("aws")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
p.GetSchemaReturn = &ProviderSchema{
Provider: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
@ -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,
},
},
},
},
}
@ -49,12 +56,9 @@ func TestContext2Input_provider(t *testing.T) {
})
var actual interface{}
p.ConfigureFn = func(c *ResourceConfig) error {
actual = c.Config["foo"]
return nil
}
p.ValidateFn = func(c *ResourceConfig) ([]string, []error) {
return nil, c.CheckSet([]string{"foo"})
p.ConfigureFn = func(req providers.ConfigureRequest) (resp providers.ConfigureResponse) {
actual = req.Config.GetAttr("foo").AsString()
return
}
if diags := ctx.Input(InputModeStd); diags.HasErrors() {
@ -85,8 +89,8 @@ func TestContext2Input_providerMulti(t *testing.T) {
m := testModule(t, "input-provider-multi")
p := testProvider("aws")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
p.GetSchemaReturn = &ProviderSchema{
Provider: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
@ -98,7 +102,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,
},
},
},
},
}
@ -119,9 +130,6 @@ func TestContext2Input_providerMulti(t *testing.T) {
var actual []interface{}
var lock sync.Mutex
p.ValidateFn = func(c *ResourceConfig) ([]string, []error) {
return nil, c.CheckSet([]string{"foo"})
}
if diags := ctx.Input(InputModeStd); diags.HasErrors() {
t.Fatalf("input errors: %s", diags.Err())
@ -131,11 +139,11 @@ func TestContext2Input_providerMulti(t *testing.T) {
t.Fatalf("plan errors: %s", diags.Err())
}
p.ConfigureFn = func(c *ResourceConfig) error {
p.ConfigureFn = func(req providers.ConfigureRequest) (resp providers.ConfigureResponse) {
lock.Lock()
defer lock.Unlock()
actual = append(actual, c.Config["foo"])
return nil
actual = append(actual, req.Config.GetAttr("foo").AsString())
return
}
if _, diags := ctx.Apply(); diags.HasErrors() {
t.Fatalf("apply errors: %s", diags.Err())
@ -150,8 +158,8 @@ func TestContext2Input_providerMulti(t *testing.T) {
func TestContext2Input_providerOnce(t *testing.T) {
m := testModule(t, "input-provider-once")
p := testProvider("aws")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
@ -159,25 +167,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())
}
@ -189,8 +178,8 @@ func TestContext2Input_providerId(t *testing.T) {
m := testModule(t, "input-provider")
p := testProvider("aws")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
p.GetSchemaReturn = &ProviderSchema{
Provider: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
@ -202,7 +191,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,
},
},
},
},
}
@ -215,9 +211,9 @@ func TestContext2Input_providerId(t *testing.T) {
})
var actual interface{}
p.ConfigureFn = func(c *ResourceConfig) error {
actual = c.Config["foo"]
return nil
p.ConfigureFn = func(req providers.ConfigureRequest) (resp providers.ConfigureResponse) {
actual = req.Config.GetAttr("foo").AsString()
return
}
input.InputReturnMap = map[string]string{
@ -247,8 +243,8 @@ func TestContext2Input_providerOnly(t *testing.T) {
m := testModule(t, "input-provider-vars")
p := testProvider("aws")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
p.GetSchemaReturn = &ProviderSchema{
Provider: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
@ -288,9 +284,9 @@ func TestContext2Input_providerOnly(t *testing.T) {
}
var actual interface{}
p.ConfigureFn = func(c *ResourceConfig) error {
actual = c.Config["foo"]
return nil
p.ConfigureFn = func(req providers.ConfigureRequest) (resp providers.ConfigureResponse) {
actual = req.Config.GetAttr("foo").AsString()
return
}
if err := ctx.Input(InputModeProvider); err != nil {
@ -321,8 +317,8 @@ func TestContext2Input_providerVars(t *testing.T) {
input := new(MockUIInput)
m := testModule(t, "input-provider-with-vars")
p := testProvider("aws")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
@ -342,15 +338,10 @@ func TestContext2Input_providerVars(t *testing.T) {
}
var actual interface{}
/*p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
c.Config["bar"] = "baz"
return c, nil
}*/
p.ConfigureFn = func(c *ResourceConfig) error {
actual, _ = c.Get("foo")
return nil
p.ConfigureFn = func(req providers.ConfigureRequest) (resp providers.ConfigureResponse) {
actual = req.Config.GetAttr("foo").AsString()
return
}
if diags := ctx.Input(InputModeStd); diags.HasErrors() {
t.Fatalf("input errors: %s", diags.Err())
}
@ -372,8 +363,8 @@ func TestContext2Input_providerVarsModuleInherit(t *testing.T) {
input := new(MockUIInput)
m := testModule(t, "input-provider-with-vars-and-module")
p := testProvider("aws")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
@ -382,16 +373,6 @@ func TestContext2Input_providerVarsModuleInherit(t *testing.T) {
UIInput: input,
})
/*p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
if errs := c.CheckSet([]string{"access_key"}); len(errs) > 0 {
return c, errs[0]
}
return c, nil
}*/
p.ConfigureFn = func(c *ResourceConfig) error {
return nil
}
if diags := ctx.Input(InputModeStd); diags.HasErrors() {
t.Fatalf("input errors: %s", diags.Err())
}
@ -402,8 +383,8 @@ func TestContext2Input_submoduleTriggersInvalidCount(t *testing.T) {
input := new(MockUIInput)
m := testModule(t, "input-submodule-count")
p := testProvider("aws")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
@ -412,13 +393,6 @@ func TestContext2Input_submoduleTriggersInvalidCount(t *testing.T) {
UIInput: input,
})
/*p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
return c, nil
}*/
p.ConfigureFn = func(c *ResourceConfig) error {
return nil
}
if diags := ctx.Input(InputModeStd); diags.HasErrors() {
t.Fatalf("input errors: %s", diags.Err())
}

File diff suppressed because it is too large Load Diff

View File

@ -52,7 +52,7 @@ func TestContext2Refresh(t *testing.T) {
p.ReadResourceResponse = providers.ReadResourceResponse{
NewState: readState,
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
s, diags := ctx.Refresh()
if diags.HasErrors() {
@ -282,7 +282,7 @@ func TestContext2Refresh_targeted(t *testing.T) {
NewState: req.PriorState,
}
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
_, diags := ctx.Refresh()
if diags.HasErrors() {
@ -361,7 +361,7 @@ func TestContext2Refresh_targetedCount(t *testing.T) {
NewState: req.PriorState,
}
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
_, diags := ctx.Refresh()
if diags.HasErrors() {
@ -448,7 +448,7 @@ func TestContext2Refresh_targetedCountIndex(t *testing.T) {
NewState: req.PriorState,
}
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
_, diags := ctx.Refresh()
if diags.HasErrors() {
@ -480,7 +480,7 @@ func TestContext2Refresh_moduleComputedVar(t *testing.T) {
},
},
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
m := testModule(t, "refresh-module-computed-var")
ctx := testContext2(t, &ContextOpts{
@ -517,7 +517,7 @@ func TestContext2Refresh_delete(t *testing.T) {
p.ReadResourceResponse = providers.ReadResourceResponse{
NewState: cty.NullVal(p.GetSchemaReturn.ResourceTypes["aws_instance"].ImpliedType()),
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
s, diags := ctx.Refresh()
if diags.HasErrors() {
@ -547,7 +547,7 @@ func TestContext2Refresh_ignoreUncreated(t *testing.T) {
"id": cty.StringVal("foo"),
}),
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
_, diags := ctx.Refresh()
if diags.HasErrors() {
@ -561,7 +561,7 @@ func TestContext2Refresh_ignoreUncreated(t *testing.T) {
func TestContext2Refresh_hook(t *testing.T) {
h := new(MockHook)
p := testProvider("aws")
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
m := testModule(t, "refresh-basic")
state := states.NewState()
@ -623,7 +623,7 @@ func TestContext2Refresh_modules(t *testing.T) {
NewState: new,
}
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
s, diags := ctx.Refresh()
if diags.HasErrors() {
@ -640,7 +640,7 @@ func TestContext2Refresh_modules(t *testing.T) {
func TestContext2Refresh_moduleInputComputedOutput(t *testing.T) {
m := testModule(t, "refresh-module-input-computed-output")
p := testProvider("aws")
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
p.GetSchemaReturn = &ProviderSchema{
Provider: &configschema.Block{},
ResourceTypes: map[string]*configschema.Block{
@ -675,7 +675,7 @@ func TestContext2Refresh_moduleInputComputedOutput(t *testing.T) {
func TestContext2Refresh_moduleVarModule(t *testing.T) {
m := testModule(t, "refresh-module-var-module")
p := testProvider("aws")
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
@ -705,7 +705,7 @@ func TestContext2Refresh_noState(t *testing.T) {
"id": cty.StringVal("foo"),
}),
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
if _, diags := ctx.Refresh(); diags.HasErrors() {
t.Fatalf("refresh errs: %s", diags.Err())
@ -726,12 +726,13 @@ func TestContext2Refresh_output(t *testing.T) {
"foo": {
Type: cty.String,
Optional: true,
Computed: true,
},
},
},
},
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
m := testModule(t, "refresh-output")
@ -767,7 +768,7 @@ func TestContext2Refresh_outputPartial(t *testing.T) {
// Refresh creates a partial plan for any instances that don't have
// remote objects yet, to get stub values for interpolation. Therefore
// we need to make DiffFn available to let that complete.
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
p.GetSchemaReturn = &ProviderSchema{
Provider: &configschema.Block{},
@ -839,7 +840,7 @@ func TestContext2Refresh_stateBasic(t *testing.T) {
}
p.ReadResourceFn = nil
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
p.ReadResourceResponse = providers.ReadResourceResponse{
NewState: readStateVal,
}
@ -948,7 +949,7 @@ func TestContext2Refresh_dataState(t *testing.T) {
State: readStateVal,
}
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
s, diags := ctx.Refresh()
if diags.HasErrors() {
@ -1014,7 +1015,7 @@ func TestContext2Refresh_dataStateRefData(t *testing.T) {
State: cty.ObjectVal(m),
}
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
s, diags := ctx.Refresh()
if diags.HasErrors() {
@ -1052,7 +1053,7 @@ func TestContext2Refresh_tainted(t *testing.T) {
NewState: cty.ObjectVal(m),
}
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
s, diags := ctx.Refresh()
if diags.HasErrors() {
@ -1076,8 +1077,8 @@ func TestContext2Refresh_tainted(t *testing.T) {
func TestContext2Refresh_unknownProvider(t *testing.T) {
m := testModule(t, "refresh-unknown-provider")
p := testProvider("aws")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
state := states.NewState()
root := state.EnsureModule(addrs.RootModuleInstance)
@ -1140,7 +1141,7 @@ func TestContext2Refresh_vars(t *testing.T) {
}
p.ReadResourceFn = nil
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
p.ReadResourceResponse = providers.ReadResourceResponse{
NewState: readStateVal,
}
@ -1194,7 +1195,7 @@ func TestContext2Refresh_orphanModule(t *testing.T) {
NewState: req.PriorState,
}
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
state := states.NewState()
root := state.EnsureModule(addrs.RootModuleInstance)
@ -1264,7 +1265,7 @@ func TestContext2Validate(t *testing.T) {
},
},
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
m := testModule(t, "validate-good")
c := testContext2(t, &ContextOpts{
@ -1283,8 +1284,8 @@ func TestContext2Validate(t *testing.T) {
func TestContext2Refresh_updateProviderInState(t *testing.T) {
m := testModule(t, "update-resource-provider")
p := testProvider("aws")
p.DiffFn = testDiffFn
p.ApplyFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
state := states.NewState()
root := state.EnsureModule(addrs.RootModuleInstance)
@ -1337,7 +1338,7 @@ func TestContext2Refresh_schemaUpgradeFlatmap(t *testing.T) {
"name": cty.StringVal("foo"),
}),
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
s := states.BuildState(func(s *states.SyncState) {
s.SetResourceInstanceCurrent(
@ -1424,7 +1425,7 @@ func TestContext2Refresh_schemaUpgradeJSON(t *testing.T) {
"name": cty.StringVal("foo"),
}),
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
s := states.BuildState(func(s *states.SyncState) {
s.SetResourceInstanceCurrent(
@ -1502,7 +1503,7 @@ data "aws_data_source" "foo" {
resp.State = req.Config
return
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Config: m,
@ -1543,7 +1544,7 @@ func TestContext2Refresh_dataResourceDependsOn(t *testing.T) {
},
},
}
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
p.ReadDataSourceResponse = providers.ReadDataSourceResponse{
State: cty.ObjectVal(map[string]cty.Value{
"compute": cty.StringVal("value"),
@ -1652,8 +1653,8 @@ resource "aws_instance" "foo" {
})
p := testProvider("aws")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Config: m,
@ -1721,8 +1722,8 @@ resource "aws_instance" "bar" {
})
p := testProvider("aws")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Config: m,

View File

@ -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
}
case []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()
}
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 {

View File

@ -150,6 +150,7 @@ func TestContext2Validate_computedVar(t *testing.T) {
ResourceTypes: map[string]*configschema.Block{
"test_instance": {
Attributes: map[string]*configschema.Attribute{
"id": {Type: cty.String, Computed: true},
"value": {Type: cty.String, Optional: true},
},
},
@ -165,22 +166,22 @@ func TestContext2Validate_computedVar(t *testing.T) {
},
})
p.ValidateFn = func(c *ResourceConfig) ([]string, []error) {
if !c.IsComputed("value") {
return nil, []error{fmt.Errorf("value isn't computed")}
p.PrepareProviderConfigFn = func(req providers.PrepareProviderConfigRequest) (resp providers.PrepareProviderConfigResponse) {
val := req.Config.GetAttr("value")
if val.IsKnown() {
resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("value isn't computed"))
}
return nil, c.CheckSet([]string{"value"})
}
p.ConfigureFn = func(c *ResourceConfig) error {
return fmt.Errorf("Configure should not be called for provider")
return
}
diags := c.Validate()
if diags.HasErrors() {
t.Fatalf("unexpected error: %s", diags.Err())
}
if p.ConfigureCalled {
t.Fatal("Configure should not be called for provider")
}
}
func TestContext2Validate_computedInFunction(t *testing.T) {
@ -464,8 +465,11 @@ func TestContext2Validate_moduleProviderVar(t *testing.T) {
},
})
p.ValidateFn = func(c *ResourceConfig) ([]string, []error) {
return nil, c.CheckSet([]string{"foo"})
p.PrepareProviderConfigFn = func(req providers.PrepareProviderConfigRequest) (resp providers.PrepareProviderConfigResponse) {
if req.Config.GetAttr("foo").IsNull() {
resp.Diagnostics = resp.Diagnostics.Append(errors.New("foo is null"))
}
return
}
diags := c.Validate()
@ -499,8 +503,11 @@ func TestContext2Validate_moduleProviderInheritUnused(t *testing.T) {
},
})
p.ValidateFn = func(c *ResourceConfig) ([]string, []error) {
return nil, c.CheckSet([]string{"foo"})
p.PrepareProviderConfigFn = func(req providers.PrepareProviderConfigRequest) (resp providers.PrepareProviderConfigResponse) {
if req.Config.GetAttr("foo").IsNull() {
resp.Diagnostics = resp.Diagnostics.Append(errors.New("foo is null"))
}
return
}
diags := c.Validate()
@ -921,8 +928,8 @@ func TestContext2Validate_targetedDestroy(t *testing.T) {
m := testModule(t, "validate-targeted")
p := testProvider("aws")
pr := simpleMockProvisioner()
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
p.GetSchemaReturn = &ProviderSchema{
ResourceTypes: map[string]*configschema.Block{
"aws_instance": {
@ -1010,8 +1017,8 @@ func TestContext2Validate_interpolateVar(t *testing.T) {
m := testModule(t, "input-interpolate-var")
p := testProvider("null")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
p.GetSchemaReturn = &ProviderSchema{
ResourceTypes: map[string]*configschema.Block{
"template_file": {
@ -1043,8 +1050,8 @@ func TestContext2Validate_interpolateComputedModuleVarDef(t *testing.T) {
m := testModule(t, "validate-computed-module-var-ref")
p := testProvider("aws")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
p.GetSchemaReturn = &ProviderSchema{
ResourceTypes: map[string]*configschema.Block{
"aws_instance": {
@ -1075,8 +1082,8 @@ func TestContext2Validate_interpolateMap(t *testing.T) {
m := testModule(t, "issue-9549")
p := testProvider("template")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
p.ApplyResourceChangeFn = testApplyFn
p.PlanResourceChangeFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Config: m,
@ -1475,7 +1482,7 @@ resource "aws_instance" "foo" {
})
p := testProvider("aws")
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
@ -1504,7 +1511,7 @@ resource "aws_instance" "foo" {
})
p := testProvider("aws")
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
@ -1536,7 +1543,7 @@ resource "aws_instance" "foo" {
})
p := testProvider("aws")
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
@ -1619,7 +1626,7 @@ output "out" {
})
p := testProvider("aws")
p.DiffFn = testDiffFn
p.PlanResourceChangeFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{

View File

@ -725,26 +725,6 @@ func processIgnoreChangesIndividual(prior, config cty.Value, ignoreChanges []hcl
return ret, nil
}
// a group of key-*ResourceAttrDiff pairs from the same flatmapped container
type flatAttrDiff map[string]*ResourceAttrDiff
// we need to keep all keys if any of them have a diff that's not ignored
func (f flatAttrDiff) keepDiff(ignoreChanges map[string]bool) bool {
for k, v := range f {
ignore := false
for attr := range ignoreChanges {
if strings.HasPrefix(k, attr) {
ignore = true
}
}
if !v.Empty() && !v.NewComputed && !ignore {
return true
}
}
return false
}
// EvalDiffDestroy is an EvalNode implementation that returns a plain
// destroy diff.
type EvalDiffDestroy struct {

View File

@ -2,7 +2,6 @@ package terraform
import (
"encoding/json"
"fmt"
"sync"
"github.com/zclconf/go-cty/cty"
@ -10,7 +9,6 @@ import (
"github.com/hashicorp/terraform/configs/hcl2shim"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/tfdiags"
)
var _ providers.Interface = (*MockProvider)(nil)
@ -52,7 +50,7 @@ type MockProvider struct {
ConfigureCalled bool
ConfigureResponse providers.ConfigureResponse
ConfigureRequest providers.ConfigureRequest
ConfigureNewFn func(providers.ConfigureRequest) providers.ConfigureResponse // Named ConfigureNewFn so we can still have the legacy ConfigureFn declared below
ConfigureFn func(providers.ConfigureRequest) providers.ConfigureResponse
StopCalled bool
StopFn func() error
@ -88,15 +86,6 @@ 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)
}
func (p *MockProvider) GetSchema() providers.GetSchemaResponse {
@ -154,19 +143,6 @@ func (p *MockProvider) ValidateResourceTypeConfig(r providers.ValidateResourceTy
p.ValidateResourceTypeConfigCalled = true
p.ValidateResourceTypeConfigRequest = r
if p.ValidateFn != nil {
resp := p.getSchema()
schema := resp.Provider.Block
rc := NewResourceConfigShimmed(r.Config, schema)
warns, errs := p.ValidateFn(rc)
ret := providers.ValidateResourceTypeConfigResponse{}
for _, warn := range warns {
ret.Diagnostics = ret.Diagnostics.Append(tfdiags.SimpleWarning(warn))
}
for _, err := range errs {
ret.Diagnostics = ret.Diagnostics.Append(err)
}
}
if p.ValidateResourceTypeConfigFn != nil {
return p.ValidateResourceTypeConfigFn(r)
}
@ -235,19 +211,7 @@ func (p *MockProvider) Configure(r providers.ConfigureRequest) providers.Configu
p.ConfigureRequest = r
if p.ConfigureFn != nil {
resp := p.getSchema()
schema := resp.Provider.Block
rc := NewResourceConfigShimmed(r.Config, schema)
ret := providers.ConfigureResponse{}
err := p.ConfigureFn(rc)
if err != nil {
ret.Diagnostics = ret.Diagnostics.Append(err)
}
return ret
}
if p.ConfigureNewFn != nil {
return p.ConfigureNewFn(r)
return p.ConfigureFn(r)
}
return p.ConfigureResponse
@ -296,49 +260,6 @@ func (p *MockProvider) PlanResourceChange(r providers.PlanResourceChangeRequest)
p.PlanResourceChangeCalled = true
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
}
if p.PlanResourceChangeFn != nil {
return p.PlanResourceChangeFn(r)
}
@ -352,92 +273,6 @@ func (p *MockProvider) ApplyResourceChange(r providers.ApplyResourceChangeReques
p.ApplyResourceChangeRequest = r
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
}
if p.ApplyResourceChangeFn != nil {
return p.ApplyResourceChangeFn(r)
}

View File

@ -1,12 +1,8 @@
package terraform
import (
"fmt"
"sync"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/convert"
"github.com/hashicorp/terraform/provisioners"
)
@ -39,12 +35,6 @@ type MockProvisioner struct {
CloseCalled bool
CloseResponse error
CloseFn func() 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.
ApplyFn func(rs *InstanceState, c *ResourceConfig) error
}
func (p *MockProvisioner) GetSchema() provisioners.GetSchemaResponse {
@ -79,45 +69,6 @@ func (p *MockProvisioner) ProvisionResource(r provisioners.ProvisionResourceRequ
p.ProvisionResourceCalled = true
p.ProvisionResourceRequest = r
if p.ApplyFn != nil {
if !r.Config.IsKnown() {
panic(fmt.Sprintf("cannot provision with unknown value: %#v", r.Config))
}
schema := p.getSchema()
rc := NewResourceConfigShimmed(r.Config, schema.Provisioner)
connVal := r.Connection
connMap := map[string]string{}
if !connVal.IsNull() && connVal.IsKnown() {
for it := connVal.ElementIterator(); it.Next(); {
ak, av := it.Element()
name := ak.AsString()
if !av.IsKnown() || av.IsNull() {
continue
}
av, _ = convert.Convert(av, cty.String)
connMap[name] = av.AsString()
}
}
// We no longer pass the full instance state to a provisioner, so we'll
// construct a partial one that should be good enough for what existing
// test mocks need.
is := &InstanceState{
Ephemeral: EphemeralState{
ConnInfo: connMap,
},
}
var resp provisioners.ProvisionResourceResponse
err := p.ApplyFn(is, rc)
if err != nil {
resp.Diagnostics = resp.Diagnostics.Append(err)
}
return resp
}
if p.ProvisionResourceFn != nil {
fn := p.ProvisionResourceFn
return fn(r)

View File

@ -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
`

View File

@ -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
}

View File

@ -1,5 +1,5 @@
provider "aws" {
value = "${test_instance.foo.value}"
value = test_instance.foo.id
}
resource "aws_instance" "bar" {}

View File

@ -1,4 +1,3 @@
resource "aws_instance" "foo" {
num = "2"
compute = "unknown"
}

View File

@ -1,5 +1,5 @@
provider "aws" {
value = "${test_instance.foo.value}"
value = test_instance.foo.id
}
resource "aws_instance" "bar" {}

View File

@ -1,7 +1,7 @@
variable "value" {}
provider "aws" {
foo = "${var.value}"
foo = var.value
}
resource "aws_instance" "foo" {}

View File

@ -3,5 +3,5 @@ variable "provider_var" {}
module "child" {
source = "./child"
value = "${var.provider_var}"
value = var.provider_var
}