mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-26 17:01:04 -06:00
terraform: re-diff on apply
This commit is contained in:
parent
84cf644a30
commit
92ffbf2880
@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/config"
|
"github.com/hashicorp/terraform/config"
|
||||||
@ -29,7 +30,15 @@ func (s *State) init() {
|
|||||||
func (s *State) String() string {
|
func (s *State) String() string {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
for k, rs := range s.Resources {
|
names := make([]string, 0, len(s.Resources))
|
||||||
|
for name, _ := range s.Resources {
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
sort.Strings(names)
|
||||||
|
|
||||||
|
for _, k := range names {
|
||||||
|
rs := s.Resources[k]
|
||||||
|
|
||||||
buf.WriteString(fmt.Sprintf("%s:\n", k))
|
buf.WriteString(fmt.Sprintf("%s:\n", k))
|
||||||
buf.WriteString(fmt.Sprintf(" ID = %s\n", rs.ID))
|
buf.WriteString(fmt.Sprintf(" ID = %s\n", rs.ID))
|
||||||
|
|
||||||
|
@ -136,7 +136,13 @@ func (t *Terraform) applyWalkFn(
|
|||||||
result.init()
|
result.init()
|
||||||
|
|
||||||
cb := func(r *Resource) (map[string]string, error) {
|
cb := func(r *Resource) (map[string]string, error) {
|
||||||
rs, err := r.Provider.Apply(r.State, r.Diff)
|
// Get the latest diff since there are no computed values anymore
|
||||||
|
diff, err := r.Provider.Diff(r.State, r.Config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rs, err := r.Provider.Apply(r.State, diff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package terraform
|
package terraform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@ -228,6 +229,33 @@ func TestTerraformApply(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTerraformApply_compute(t *testing.T) {
|
||||||
|
// This tests that computed variables are properly re-diffed
|
||||||
|
// to get the value prior to application (Apply).
|
||||||
|
tf := testTerraform(t, "apply-compute")
|
||||||
|
|
||||||
|
s := &State{}
|
||||||
|
p, err := tf.Plan(s)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set meta to change behavior so that computed variables are filled
|
||||||
|
testProviderMock(testProvider(tf, "aws_instance.foo")).Meta =
|
||||||
|
"compute"
|
||||||
|
|
||||||
|
state, err := tf.Apply(p)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := strings.TrimSpace(state.String())
|
||||||
|
expected := strings.TrimSpace(testTerraformApplyComputeStr)
|
||||||
|
if actual != expected {
|
||||||
|
t.Fatalf("bad: \n%s", actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestTerraformPlan(t *testing.T) {
|
func TestTerraformPlan(t *testing.T) {
|
||||||
tf := testTerraform(t, "plan-good")
|
tf := testTerraform(t, "plan-good")
|
||||||
|
|
||||||
@ -324,6 +352,8 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return func() (ResourceProvider, error) {
|
return func() (ResourceProvider, error) {
|
||||||
|
p := &MockResourceProvider{Meta: n}
|
||||||
|
|
||||||
applyFn := func(
|
applyFn := func(
|
||||||
s *ResourceState,
|
s *ResourceState,
|
||||||
d *ResourceDiff) (*ResourceState, error) {
|
d *ResourceDiff) (*ResourceState, error) {
|
||||||
@ -361,11 +391,20 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if k == "compute" {
|
if k == "compute" {
|
||||||
diff.Attributes[v.(string)] = &ResourceAttrDiff{
|
attrDiff := &ResourceAttrDiff{
|
||||||
Old: "",
|
Old: "",
|
||||||
New: "",
|
New: "",
|
||||||
NewComputed: true,
|
NewComputed: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the value of Meta turns into "compute", then we
|
||||||
|
// fill the computed values.
|
||||||
|
if mv, ok := p.Meta.(string); ok && mv == "compute" {
|
||||||
|
attrDiff.NewComputed = false
|
||||||
|
attrDiff.New = fmt.Sprintf("computed_%s", v.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
diff.Attributes[v.(string)] = attrDiff
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,15 +447,12 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory {
|
|||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
result := &MockResourceProvider{
|
p.ApplyFn = applyFn
|
||||||
Meta: n,
|
p.DiffFn = diffFn
|
||||||
ApplyFn: applyFn,
|
p.RefreshFn = refreshFn
|
||||||
DiffFn: diffFn,
|
p.ResourcesReturn = resources
|
||||||
RefreshFn: refreshFn,
|
|
||||||
ResourcesReturn: resources,
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,6 +538,18 @@ aws_instance.foo:
|
|||||||
num = 2
|
num = 2
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const testTerraformApplyComputeStr = `
|
||||||
|
aws_instance.bar:
|
||||||
|
ID = foo
|
||||||
|
type = aws_instance
|
||||||
|
foo = computed_id
|
||||||
|
aws_instance.foo:
|
||||||
|
ID = foo
|
||||||
|
type = aws_instance
|
||||||
|
num = 2
|
||||||
|
id = computed_id
|
||||||
|
`
|
||||||
|
|
||||||
const testTerraformPlanStr = `
|
const testTerraformPlanStr = `
|
||||||
UPDATE: aws_instance.bar
|
UPDATE: aws_instance.bar
|
||||||
foo: "" => "2"
|
foo: "" => "2"
|
||||||
|
8
terraform/test-fixtures/apply-compute/main.tf
Normal file
8
terraform/test-fixtures/apply-compute/main.tf
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
resource "aws_instance" "foo" {
|
||||||
|
num = "2"
|
||||||
|
compute = "id"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_instance" "bar" {
|
||||||
|
foo = "${aws_instance.foo.id}"
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user