2017-01-19 05:47:56 +01:00
|
|
|
package local
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"testing"
|
|
|
|
|
2018-10-04 00:50:04 +02:00
|
|
|
"github.com/hashicorp/terraform/providers"
|
|
|
|
|
2017-01-19 05:47:56 +01:00
|
|
|
"github.com/hashicorp/terraform/backend"
|
2018-09-28 23:04:57 +02:00
|
|
|
"github.com/hashicorp/terraform/configs/configschema"
|
2019-01-09 03:39:14 +01:00
|
|
|
"github.com/hashicorp/terraform/internal/initwd"
|
2017-01-19 05:47:56 +01:00
|
|
|
"github.com/hashicorp/terraform/terraform"
|
2018-05-23 04:57:04 +02:00
|
|
|
"github.com/zclconf/go-cty/cty"
|
2017-01-19 05:47:56 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestLocal_refresh(t *testing.T) {
|
2018-03-28 16:54:08 +02:00
|
|
|
b, cleanup := TestLocal(t)
|
|
|
|
defer cleanup()
|
|
|
|
|
2018-05-23 04:57:04 +02:00
|
|
|
p := TestLocalProvider(t, b, "test", refreshFixtureSchema())
|
2017-01-19 05:47:56 +01:00
|
|
|
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"),
|
|
|
|
})}
|
2017-01-19 05:47:56 +01:00
|
|
|
|
2019-06-30 09:38:36 +02:00
|
|
|
op, configCleanup := testOperationRefresh(t, "./testdata/refresh")
|
2018-03-21 02:43:02 +01:00
|
|
|
defer configCleanup()
|
2017-01-19 05:47:56 +01:00
|
|
|
|
|
|
|
run, err := b.Operation(context.Background(), op)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("bad: %s", err)
|
|
|
|
}
|
|
|
|
<-run.Done()
|
|
|
|
|
2018-09-28 23:04:57 +02:00
|
|
|
if !p.ReadResourceCalled {
|
|
|
|
t.Fatal("ReadResource should be called")
|
2017-01-19 05:47:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
checkState(t, b.StateOutPath, `
|
|
|
|
test_instance.foo:
|
|
|
|
ID = yes
|
2020-02-13 21:32:58 +01:00
|
|
|
provider = provider["registry.terraform.io/-/test"]
|
2017-01-19 05:47:56 +01:00
|
|
|
`)
|
|
|
|
}
|
|
|
|
|
2018-03-21 02:43:02 +01:00
|
|
|
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())
|
2017-02-22 22:08:03 +01:00
|
|
|
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"),
|
|
|
|
})}
|
2017-02-22 22:08:03 +01:00
|
|
|
|
2019-06-30 09:38:36 +02:00
|
|
|
op, configCleanup := testOperationRefresh(t, "./testdata/empty")
|
2018-03-21 02:43:02 +01:00
|
|
|
defer configCleanup()
|
2017-02-22 22:08:03 +01:00
|
|
|
|
|
|
|
run, err := b.Operation(context.Background(), op)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("bad: %s", err)
|
|
|
|
}
|
|
|
|
<-run.Done()
|
|
|
|
|
2018-09-28 23:04:57 +02:00
|
|
|
if !p.ReadResourceCalled {
|
|
|
|
t.Fatal("ReadResource should be called")
|
2017-02-22 22:08:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
checkState(t, b.StateOutPath, `
|
|
|
|
test_instance.foo:
|
|
|
|
ID = yes
|
2020-02-13 21:32:58 +01:00
|
|
|
provider = provider["registry.terraform.io/-/test"]
|
2017-02-22 22:08:03 +01:00
|
|
|
`)
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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())
|
2017-02-22 22:08:03 +01:00
|
|
|
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"),
|
|
|
|
})}
|
2017-02-22 22:08:03 +01:00
|
|
|
|
|
|
|
b.OpInput = true
|
|
|
|
|
2019-06-30 09:38:36 +02:00
|
|
|
op, configCleanup := testOperationRefresh(t, "./testdata/empty")
|
2018-03-21 02:43:02 +01:00
|
|
|
defer configCleanup()
|
2017-02-22 22:08:03 +01:00
|
|
|
|
|
|
|
run, err := b.Operation(context.Background(), op)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("bad: %s", err)
|
|
|
|
}
|
|
|
|
<-run.Done()
|
|
|
|
|
2018-09-28 23:04:57 +02:00
|
|
|
if !p.ReadResourceCalled {
|
|
|
|
t.Fatal("ReadResource should be called")
|
2017-02-22 22:08:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
checkState(t, b.StateOutPath, `
|
|
|
|
test_instance.foo:
|
|
|
|
ID = yes
|
2020-02-13 21:32:58 +01:00
|
|
|
provider = provider["registry.terraform.io/-/test"]
|
2017-02-22 22:08:03 +01:00
|
|
|
`)
|
|
|
|
}
|
|
|
|
|
2017-01-19 05:47:56 +01:00
|
|
|
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())
|
2017-01-19 05:47:56 +01:00
|
|
|
terraform.TestStateFile(t, b.StatePath, testRefreshState())
|
|
|
|
|
2018-05-23 04:57:04 +02:00
|
|
|
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-05-23 04:57:04 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
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"),
|
|
|
|
})}
|
2017-01-19 05:47:56 +01:00
|
|
|
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"}
|
|
|
|
|
2019-06-30 09:38:36 +02:00
|
|
|
op, configCleanup := testOperationRefresh(t, "./testdata/refresh-var-unset")
|
2018-03-21 02:43:02 +01:00
|
|
|
defer configCleanup()
|
2017-01-19 05:47:56 +01:00
|
|
|
op.UIIn = b.ContextOpts.UIInput
|
|
|
|
|
|
|
|
run, err := b.Operation(context.Background(), op)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("bad: %s", err)
|
|
|
|
}
|
|
|
|
<-run.Done()
|
|
|
|
|
2018-09-28 23:04:57 +02:00
|
|
|
if !p.ReadResourceCalled {
|
|
|
|
t.Fatal("ReadResource should be called")
|
2017-01-19 05:47:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
checkState(t, b.StateOutPath, `
|
|
|
|
test_instance.foo:
|
|
|
|
ID = yes
|
2020-02-13 21:32:58 +01:00
|
|
|
provider = provider["registry.terraform.io/-/test"]
|
2017-01-19 05:47:56 +01:00
|
|
|
`)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestLocal_refreshValidate(t *testing.T) {
|
2018-03-28 16:54:08 +02:00
|
|
|
b, cleanup := TestLocal(t)
|
|
|
|
defer cleanup()
|
2018-05-23 04:57:04 +02:00
|
|
|
p := TestLocalProvider(t, b, "test", refreshFixtureSchema())
|
2017-01-19 05:47:56 +01:00
|
|
|
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"),
|
|
|
|
})}
|
2017-01-19 05:47:56 +01:00
|
|
|
|
|
|
|
// Enable validation
|
|
|
|
b.OpValidation = true
|
|
|
|
|
2019-06-30 09:38:36 +02:00
|
|
|
op, configCleanup := testOperationRefresh(t, "./testdata/refresh")
|
2018-03-21 02:43:02 +01:00
|
|
|
defer configCleanup()
|
2017-01-19 05:47:56 +01:00
|
|
|
|
|
|
|
run, err := b.Operation(context.Background(), op)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("bad: %s", err)
|
|
|
|
}
|
|
|
|
<-run.Done()
|
|
|
|
|
2018-10-19 15:29:14 +02:00
|
|
|
if !p.PrepareProviderConfigCalled {
|
|
|
|
t.Fatal("Prepare provider config should be called")
|
2017-01-19 05:47:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
checkState(t, b.StateOutPath, `
|
|
|
|
test_instance.foo:
|
|
|
|
ID = yes
|
2020-02-13 21:32:58 +01:00
|
|
|
provider = provider["registry.terraform.io/-/test"]
|
2017-01-19 05:47:56 +01:00
|
|
|
`)
|
|
|
|
}
|
|
|
|
|
2018-03-21 02:43:02 +01:00
|
|
|
func testOperationRefresh(t *testing.T, configDir string) (*backend.Operation, func()) {
|
|
|
|
t.Helper()
|
|
|
|
|
2019-01-09 03:39:14 +01:00
|
|
|
_, configLoader, configCleanup := initwd.MustLoadConfigForTests(t, configDir)
|
2018-03-21 02:43:02 +01:00
|
|
|
|
2017-01-19 05:47:56 +01:00
|
|
|
return &backend.Operation{
|
2018-03-21 02:43:02 +01:00
|
|
|
Type: backend.OperationTypeRefresh,
|
|
|
|
ConfigDir: configDir,
|
|
|
|
ConfigLoader: configLoader,
|
|
|
|
}, configCleanup
|
2017-01-19 05:47:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2018-05-23 04:57:04 +02:00
|
|
|
|
|
|
|
// refreshFixtureSchema returns a schema suitable for processing the
|
2019-06-30 09:38:36 +02:00
|
|
|
// configuration in testdata/refresh . This schema should be
|
2018-05-23 04:57:04 +02:00
|
|
|
// 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},
|
2018-05-23 04:57:04 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|