terraform/backend/local/backend_refresh_test.go

251 lines
6.4 KiB
Go
Raw Normal View History

package local
import (
"context"
"fmt"
"testing"
2018-10-04 00:50:04 +02:00
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/internal/initwd"
"github.com/hashicorp/terraform/terraform"
"github.com/zclconf/go-cty/cty"
)
func TestLocal_refresh(t *testing.T) {
2018-03-28 16:54:08 +02:00
b, cleanup := TestLocal(t)
defer cleanup()
p := TestLocalProvider(t, b, "test", refreshFixtureSchema())
terraform.TestStateFile(t, b.StatePath, testRefreshState())
2018-10-04 00:50:04 +02:00
p.ReadResourceFn = nil
p.ReadResourceResponse = providers.ReadResourceResponse{NewState: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("yes"),
})}
op, configCleanup := testOperationRefresh(t, "./testdata/refresh")
defer configCleanup()
run, err := b.Operation(context.Background(), op)
if err != nil {
t.Fatalf("bad: %s", err)
}
<-run.Done()
if !p.ReadResourceCalled {
t.Fatal("ReadResource should be called")
}
checkState(t, b.StateOutPath, `
test_instance.foo:
ID = yes
provider = provider["registry.terraform.io/-/test"]
`)
}
func TestLocal_refreshNoConfig(t *testing.T) {
2018-03-28 16:54:08 +02:00
b, cleanup := TestLocal(t)
defer cleanup()
2018-10-04 00:50:04 +02:00
p := TestLocalProvider(t, b, "test", refreshFixtureSchema())
terraform.TestStateFile(t, b.StatePath, testRefreshState())
2018-10-04 00:50:04 +02:00
p.ReadResourceFn = nil
p.ReadResourceResponse = providers.ReadResourceResponse{NewState: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("yes"),
})}
op, configCleanup := testOperationRefresh(t, "./testdata/empty")
defer configCleanup()
run, err := b.Operation(context.Background(), op)
if err != nil {
t.Fatalf("bad: %s", err)
}
<-run.Done()
if !p.ReadResourceCalled {
t.Fatal("ReadResource should be called")
}
checkState(t, b.StateOutPath, `
test_instance.foo:
ID = yes
provider = provider["registry.terraform.io/-/test"]
`)
}
// GH-12174
func TestLocal_refreshNilModuleWithInput(t *testing.T) {
2018-03-28 16:54:08 +02:00
b, cleanup := TestLocal(t)
defer cleanup()
2018-10-04 00:50:04 +02:00
p := TestLocalProvider(t, b, "test", refreshFixtureSchema())
terraform.TestStateFile(t, b.StatePath, testRefreshState())
2018-10-04 00:50:04 +02:00
p.ReadResourceFn = nil
p.ReadResourceResponse = providers.ReadResourceResponse{NewState: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("yes"),
})}
b.OpInput = true
op, configCleanup := testOperationRefresh(t, "./testdata/empty")
defer configCleanup()
run, err := b.Operation(context.Background(), op)
if err != nil {
t.Fatalf("bad: %s", err)
}
<-run.Done()
if !p.ReadResourceCalled {
t.Fatal("ReadResource should be called")
}
checkState(t, b.StateOutPath, `
test_instance.foo:
ID = yes
provider = provider["registry.terraform.io/-/test"]
`)
}
func TestLocal_refreshInput(t *testing.T) {
2018-03-28 16:54:08 +02:00
b, cleanup := TestLocal(t)
defer cleanup()
2018-10-04 00:50:04 +02:00
p := TestLocalProvider(t, b, "test", refreshFixtureSchema())
terraform.TestStateFile(t, b.StatePath, testRefreshState())
p.GetSchemaReturn = &terraform.ProviderSchema{
Provider: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"value": {Type: cty.String, Optional: true},
},
},
ResourceTypes: map[string]*configschema.Block{
"test_instance": {
Attributes: map[string]*configschema.Attribute{
"foo": {Type: cty.String, Optional: true},
2018-10-04 00:50:04 +02:00
"id": {Type: cty.String, Optional: true},
},
},
},
}
2018-10-04 00:50:04 +02:00
p.ReadResourceFn = nil
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")
}
return nil
}
// Enable input asking since it is normally disabled by default
b.OpInput = true
b.ContextOpts.UIInput = &terraform.MockUIInput{InputReturnString: "bar"}
op, configCleanup := testOperationRefresh(t, "./testdata/refresh-var-unset")
defer configCleanup()
op.UIIn = b.ContextOpts.UIInput
run, err := b.Operation(context.Background(), op)
if err != nil {
t.Fatalf("bad: %s", err)
}
<-run.Done()
if !p.ReadResourceCalled {
t.Fatal("ReadResource should be called")
}
checkState(t, b.StateOutPath, `
test_instance.foo:
ID = yes
provider = provider["registry.terraform.io/-/test"]
`)
}
func TestLocal_refreshValidate(t *testing.T) {
2018-03-28 16:54:08 +02:00
b, cleanup := TestLocal(t)
defer cleanup()
p := TestLocalProvider(t, b, "test", refreshFixtureSchema())
terraform.TestStateFile(t, b.StatePath, testRefreshState())
2018-10-04 00:50:04 +02:00
p.ReadResourceFn = nil
p.ReadResourceResponse = providers.ReadResourceResponse{NewState: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("yes"),
})}
// Enable validation
b.OpValidation = true
op, configCleanup := testOperationRefresh(t, "./testdata/refresh")
defer configCleanup()
run, err := b.Operation(context.Background(), op)
if err != nil {
t.Fatalf("bad: %s", err)
}
<-run.Done()
if !p.PrepareProviderConfigCalled {
t.Fatal("Prepare provider config should be called")
}
checkState(t, b.StateOutPath, `
test_instance.foo:
ID = yes
provider = provider["registry.terraform.io/-/test"]
`)
}
func testOperationRefresh(t *testing.T, configDir string) (*backend.Operation, func()) {
t.Helper()
_, configLoader, configCleanup := initwd.MustLoadConfigForTests(t, configDir)
return &backend.Operation{
Type: backend.OperationTypeRefresh,
ConfigDir: configDir,
ConfigLoader: configLoader,
}, configCleanup
}
// testRefreshState is just a common state that we use for testing refresh.
func testRefreshState() *terraform.State {
return &terraform.State{
Version: 2,
Modules: []*terraform.ModuleState{
&terraform.ModuleState{
Path: []string{"root"},
Resources: map[string]*terraform.ResourceState{
"test_instance.foo": &terraform.ResourceState{
Type: "test_instance",
Primary: &terraform.InstanceState{
ID: "bar",
},
},
},
Outputs: map[string]*terraform.OutputState{},
},
},
}
}
// refreshFixtureSchema returns a schema suitable for processing the
// configuration in testdata/refresh . This schema should be
// assigned to a mock provider named "test".
func refreshFixtureSchema() *terraform.ProviderSchema {
return &terraform.ProviderSchema{
ResourceTypes: map[string]*configschema.Block{
"test_instance": {
Attributes: map[string]*configschema.Attribute{
"ami": {Type: cty.String, Optional: true},
2018-10-04 00:50:04 +02:00
"id": {Type: cty.String, Computed: true},
},
},
},
}
}