|
|
|
|
@ -3,6 +3,7 @@ package schema
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"reflect"
|
|
|
|
|
"strconv"
|
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
|
|
"github.com/hashicorp/terraform/terraform"
|
|
|
|
|
@ -478,3 +479,218 @@ func TestResourceRefresh_noExists(t *testing.T) {
|
|
|
|
|
t.Fatalf("should have no state")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestResourceRefresh_needsMigration(t *testing.T) {
|
|
|
|
|
// Schema v2 it deals only in newfoo, which tracks foo as an int
|
|
|
|
|
r := &Resource{
|
|
|
|
|
SchemaVersion: 2,
|
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
|
"newfoo": &Schema{
|
|
|
|
|
Type: TypeInt,
|
|
|
|
|
Optional: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r.Read = func(d *ResourceData, m interface{}) error {
|
|
|
|
|
return d.Set("newfoo", d.Get("newfoo").(int)+1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r.MigrateState = func(
|
|
|
|
|
v int,
|
|
|
|
|
s *terraform.InstanceState,
|
|
|
|
|
meta interface{}) (*terraform.InstanceState, error) {
|
|
|
|
|
// Real state migration functions will probably switch on this value,
|
|
|
|
|
// but we'll just assert on it for now.
|
|
|
|
|
if v != 1 {
|
|
|
|
|
t.Fatalf("Expected StateSchemaVersion to be 1, got %d", v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if meta != 42 {
|
|
|
|
|
t.Fatal("Expected meta to be passed through to the migration function")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
oldfoo, err := strconv.ParseFloat(s.Attributes["oldfoo"], 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("err: %#v", err)
|
|
|
|
|
}
|
|
|
|
|
s.Attributes["newfoo"] = strconv.Itoa((int(oldfoo * 10)))
|
|
|
|
|
delete(s.Attributes, "oldfoo")
|
|
|
|
|
|
|
|
|
|
return s, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// State is v1 and deals in oldfoo, which tracked foo as a float at 1/10th
|
|
|
|
|
// the scale of newfoo
|
|
|
|
|
s := &terraform.InstanceState{
|
|
|
|
|
ID: "bar",
|
|
|
|
|
Attributes: map[string]string{
|
|
|
|
|
"oldfoo": "1.2",
|
|
|
|
|
},
|
|
|
|
|
Meta: map[string]string{
|
|
|
|
|
"schema_version": "1",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actual, err := r.Refresh(s, 42)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expected := &terraform.InstanceState{
|
|
|
|
|
ID: "bar",
|
|
|
|
|
Attributes: map[string]string{
|
|
|
|
|
"id": "bar",
|
|
|
|
|
"newfoo": "13",
|
|
|
|
|
},
|
|
|
|
|
Meta: map[string]string{
|
|
|
|
|
"schema_version": "2",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(actual, expected) {
|
|
|
|
|
t.Fatalf("bad:\n\nexpected: %#v\ngot: %#v", expected, actual)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestResourceRefresh_noMigrationNeeded(t *testing.T) {
|
|
|
|
|
r := &Resource{
|
|
|
|
|
SchemaVersion: 2,
|
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
|
"newfoo": &Schema{
|
|
|
|
|
Type: TypeInt,
|
|
|
|
|
Optional: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r.Read = func(d *ResourceData, m interface{}) error {
|
|
|
|
|
return d.Set("newfoo", d.Get("newfoo").(int)+1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r.MigrateState = func(
|
|
|
|
|
v int,
|
|
|
|
|
s *terraform.InstanceState,
|
|
|
|
|
meta interface{}) (*terraform.InstanceState, error) {
|
|
|
|
|
t.Fatal("Migrate function shouldn't be called!")
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s := &terraform.InstanceState{
|
|
|
|
|
ID: "bar",
|
|
|
|
|
Attributes: map[string]string{
|
|
|
|
|
"newfoo": "12",
|
|
|
|
|
},
|
|
|
|
|
Meta: map[string]string{
|
|
|
|
|
"schema_version": "2",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actual, err := r.Refresh(s, nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expected := &terraform.InstanceState{
|
|
|
|
|
ID: "bar",
|
|
|
|
|
Attributes: map[string]string{
|
|
|
|
|
"id": "bar",
|
|
|
|
|
"newfoo": "13",
|
|
|
|
|
},
|
|
|
|
|
Meta: map[string]string{
|
|
|
|
|
"schema_version": "2",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(actual, expected) {
|
|
|
|
|
t.Fatalf("bad:\n\nexpected: %#v\ngot: %#v", expected, actual)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestResourceRefresh_stateSchemaVersionUnset(t *testing.T) {
|
|
|
|
|
r := &Resource{
|
|
|
|
|
// Version 1 > Version 0
|
|
|
|
|
SchemaVersion: 1,
|
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
|
"newfoo": &Schema{
|
|
|
|
|
Type: TypeInt,
|
|
|
|
|
Optional: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r.Read = func(d *ResourceData, m interface{}) error {
|
|
|
|
|
return d.Set("newfoo", d.Get("newfoo").(int)+1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r.MigrateState = func(
|
|
|
|
|
v int,
|
|
|
|
|
s *terraform.InstanceState,
|
|
|
|
|
meta interface{}) (*terraform.InstanceState, error) {
|
|
|
|
|
s.Attributes["newfoo"] = s.Attributes["oldfoo"]
|
|
|
|
|
return s, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s := &terraform.InstanceState{
|
|
|
|
|
ID: "bar",
|
|
|
|
|
Attributes: map[string]string{
|
|
|
|
|
"oldfoo": "12",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actual, err := r.Refresh(s, nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expected := &terraform.InstanceState{
|
|
|
|
|
ID: "bar",
|
|
|
|
|
Attributes: map[string]string{
|
|
|
|
|
"id": "bar",
|
|
|
|
|
"newfoo": "13",
|
|
|
|
|
},
|
|
|
|
|
Meta: map[string]string{
|
|
|
|
|
"schema_version": "1",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(actual, expected) {
|
|
|
|
|
t.Fatalf("bad:\n\nexpected: %#v\ngot: %#v", expected, actual)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestResourceRefresh_migrateStateErr(t *testing.T) {
|
|
|
|
|
r := &Resource{
|
|
|
|
|
SchemaVersion: 2,
|
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
|
"newfoo": &Schema{
|
|
|
|
|
Type: TypeInt,
|
|
|
|
|
Optional: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r.Read = func(d *ResourceData, m interface{}) error {
|
|
|
|
|
t.Fatal("Read should never be called!")
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r.MigrateState = func(
|
|
|
|
|
v int,
|
|
|
|
|
s *terraform.InstanceState,
|
|
|
|
|
meta interface{}) (*terraform.InstanceState, error) {
|
|
|
|
|
return s, fmt.Errorf("triggering an error")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s := &terraform.InstanceState{
|
|
|
|
|
ID: "bar",
|
|
|
|
|
Attributes: map[string]string{
|
|
|
|
|
"oldfoo": "12",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_, err := r.Refresh(s, nil)
|
|
|
|
|
if err == nil {
|
|
|
|
|
t.Fatal("expected error, but got none!")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|