During the implementation of Consider Adding State Check Equivalents to Plan Checks, it was intended that the pre-built TestCheckFunc implementations would be deprecated. However, these deprecations were not included at that time partly because there was no satisfactory re-implementation of TestCheckResourceAttrPtr, which used the new style state checks which leverage tfjson.State, and neither TestCheckResourceAttrPair, nor TestCheckTypeSetElemAttrPair were re-implemented as it was unclear whether there was a need for such checks.
Comparison State Checks and the ValueComparer interface
The concepts from Consider Multiple Value Checking Interface have been used to implement comparison state checks to replace the built-in TestCheckFunc checks for TestCheckResourceAttrPtr, TestCheckResourceAttrPair, and TestCheckTypeSetElemAttrPair. All three implementations make use of the ValueComparer interface.
Replacement for TestCheckResourceAttrPtr - CompareValue
var _ StateCheck = &compareValue{}
type compareValue struct {
resourceAddresses []string
attributePaths []tfjsonpath.Path
stateValues []any
comparer compare.ValueComparer
}
func (e *compareValue) AddStateValue(resourceAddress string, attributePath tfjsonpath.Path) StateCheck {
e.resourceAddresses = append(e.resourceAddresses, resourceAddress)
e.attributePaths = append(e.attributePaths, attributePath)
return e
}
// CheckState implements the state check logic.
func (e *compareValue) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) {
/* ... */
err = e.comparer.CompareValues(e.stateValues...)
/* ... */
}
// CompareValue returns a state check that compares sequential values retrieved from state.
func CompareValue(comparer compare.ValueComparer) *compareValue {
return &compareValue{
comparer: comparer,
}
}
Replacement for TestCheckResourceAttrPair - CompareValuePairs
Replacement for TestCheckTypeSetElemAttrPair - CompareValueCollection
var _ StateCheck = &compareValueCollection{}
type compareValueCollection struct {
resourceAddressOne string
collectionPath []tfjsonpath.Path
resourceAddressTwo string
attributePath tfjsonpath.Path
comparer compare.ValueComparer
}
// CheckState implements the state check logic.
func (e *compareValueCollection) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) {
/* ... */
for _, v := range results {
switch resultTwo.(type) {
case []any:
errs = append(errs, e.comparer.CompareValues([]any{v}, resultTwo))
default:
errs = append(errs, e.comparer.CompareValues(v, resultTwo))
}
}
/* ... */
}
// CompareValueCollection returns a state check that iterates over each element in a collection and compares the value of each element
// with the value of an attribute using the given value comparer.
func CompareValueCollection(resourceAddressOne string, collectionPath []tfjsonpath.Path, resourceAddressTwo string, attributePath tfjsonpath.Path, comparer compare.ValueComparer) StateCheck {
return &compareValueCollection{
resourceAddressOne: resourceAddressOne,
collectionPath: collectionPath,
resourceAddressTwo: resourceAddressTwo,
attributePath: attributePath,
comparer: comparer,
}
}
Implementations of the ValueComparer interface
type ValueComparer interface {
CompareValues(values ...any) error
}
type ValuesSame struct{}
func (v ValuesSame) CompareValues(values ...any) error {
for i := 1; i < len(values); i++ {
if values[i-1] != values[i] {
return fmt.Errorf("expected values to be the same, but they differ: %v != %v", values[i-1], values[i])
}
}
return nil
}
There are implementations of the ValueComparer interface for:
ValuesSame
ValuesSameAny
ValuesDiffer
ValuesDifferAny
ValuesDifferAll
These various implementations can be used in conjunction with CompareValue, CompareValueCollection, and CompareValuePairs. In the case of CompareValueCollection, and CompareValuePairs, both ValuesSame, and ValuesSameAny comparisons, and ValuesDiffer, ValuesDifferAny, and ValuesDifferAll are equivalent as these two comparison state checks interrogate 2 values at a time.
Closes: #295 References: #282 References: #187
Background
During the implementation of Consider Adding State Check Equivalents to Plan Checks, it was intended that the pre-built
TestCheckFunc
implementations would be deprecated. However, these deprecations were not included at that time partly because there was no satisfactory re-implementation ofTestCheckResourceAttrPtr
, which used the new style state checks which leverage tfjson.State, and neitherTestCheckResourceAttrPair
, norTestCheckTypeSetElemAttrPair
were re-implemented as it was unclear whether there was a need for such checks.Comparison State Checks and the
ValueComparer
interfaceThe concepts from Consider Multiple Value Checking Interface have been used to implement comparison state checks to replace the built-in
TestCheckFunc
checks forTestCheckResourceAttrPtr
,TestCheckResourceAttrPair
, andTestCheckTypeSetElemAttrPair
. All three implementations make use of theValueComparer
interface.Replacement for
TestCheckResourceAttrPtr
-CompareValue
Replacement for
TestCheckResourceAttrPair
-CompareValuePairs
Replacement for
TestCheckTypeSetElemAttrPair
-CompareValueCollection
Implementations of the
ValueComparer
interfaceThere are implementations of the
ValueComparer
interface for:ValuesSame
ValuesSameAny
ValuesDiffer
ValuesDifferAny
ValuesDifferAll
These various implementations can be used in conjunction with
CompareValue
,CompareValueCollection
, andCompareValuePairs
. In the case ofCompareValueCollection
, andCompareValuePairs
, bothValuesSame
, andValuesSameAny
comparisons, andValuesDiffer
,ValuesDifferAny
, andValuesDifferAll
are equivalent as these two comparison state checks interrogate 2 values at a time.