add a round trip through the shims during apply

Cycle through the shim operations after Apply, to ensure that we can
converge on a stable value for for Plan. While the shims produce valid
values in both directions, helper/schema sometimes does not agree on
which containers should be empty or null.
This commit is contained in:
James Bardin 2019-01-15 11:59:15 -05:00
parent 0d1252812b
commit 0a731167db
1 changed files with 37 additions and 1 deletions

View File

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"log"
"regexp" "regexp"
"sort" "sort"
"strconv" "strconv"
@ -728,10 +729,10 @@ func (s *GRPCProviderServer) ApplyResourceChange(_ context.Context, req *proto.A
return resp, nil return resp, nil
} }
plannedState := hcl2shim.FlatmapValueFromHCL2(plannedStateVal)
if newInstanceState != nil { if newInstanceState != nil {
// here we use the planned state to check for unknown/zero containers values // here we use the planned state to check for unknown/zero containers values
// when normalizing the flatmap. // when normalizing the flatmap.
plannedState := hcl2shim.FlatmapValueFromHCL2(plannedStateVal)
newInstanceState.Attributes = normalizeFlatmapContainers(plannedState, newInstanceState.Attributes, true) newInstanceState.Attributes = normalizeFlatmapContainers(plannedState, newInstanceState.Attributes, true)
} }
@ -749,6 +750,41 @@ func (s *GRPCProviderServer) ApplyResourceChange(_ context.Context, req *proto.A
newStateVal = copyMissingValues(newStateVal, plannedStateVal) newStateVal = copyMissingValues(newStateVal, plannedStateVal)
if newInstanceState != nil {
prevVal := newStateVal
for i := 0; ; i++ {
// cycle through the shims, to ensure that the plan will create an
// identical value
shimmedState, err := res.ShimInstanceStateFromValue(prevVal)
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
shimmedState.Attributes = normalizeFlatmapContainers(shimmedState.Attributes, shimmedState.Attributes, false)
tmpVal, err := hcl2shim.HCL2ValueFromFlatmap(shimmedState.Attributes, block.ImpliedType())
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
return resp, nil
}
tmpVal = copyMissingValues(tmpVal, prevVal)
if tmpVal.RawEquals(prevVal) {
newStateVal = tmpVal
break
}
if i < 2 {
prevVal = tmpVal
continue
}
log.Printf("[ERROR] hcl2shims failed to converge for value: %#v\n", newStateVal)
break
}
}
newStateVal = copyTimeoutValues(newStateVal, plannedStateVal) newStateVal = copyTimeoutValues(newStateVal, plannedStateVal)
newStateMP, err := msgpack.Marshal(newStateVal, block.ImpliedType()) newStateMP, err := msgpack.Marshal(newStateVal, block.ImpliedType())