helper/resource: TestCheckResourceAttrPair allow nonexist
This checking helper is frequently used in provider tests for data sources, as a shorthand to verify that an attribute of the data source matches with the corresponding attribute on a managed resource. Since we now leave empty collections null in more cases, this function is sometimes effectively asked to verify that a given attribute is _unset_ in both the data source and the resource, so here we slightly adjust the definition of the check to consider two nulls to be equal to one another, which at this layer manifests as the keys not being present in the state attributes map at all. This check function didn't previously have tests, so this commit also adds a basic suite of tests, including coverage for the new behavior.
This commit is contained in:
parent
70eeec8083
commit
4c99864dad
|
@ -1146,14 +1146,17 @@ func TestCheckModuleResourceAttrPair(mpFirst []string, nameFirst string, keyFirs
|
|||
}
|
||||
|
||||
func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst string, keyFirst string, isSecond *terraform.InstanceState, nameSecond string, keySecond string) error {
|
||||
vFirst, ok := isFirst.Attributes[keyFirst]
|
||||
if !ok {
|
||||
return fmt.Errorf("%s: Attribute '%s' not found", nameFirst, keyFirst)
|
||||
vFirst, okFirst := isFirst.Attributes[keyFirst]
|
||||
vSecond, okSecond := isSecond.Attributes[keySecond]
|
||||
if okFirst != okSecond {
|
||||
if !okFirst {
|
||||
return fmt.Errorf("%s: Attribute %q not set, but %q is set in %s as %q", nameFirst, keyFirst, keySecond, nameSecond, vSecond)
|
||||
}
|
||||
return fmt.Errorf("%s: Attribute %q is %q, but %q is not set in %s", nameFirst, keyFirst, vFirst, keySecond, nameSecond)
|
||||
}
|
||||
|
||||
vSecond, ok := isSecond.Attributes[keySecond]
|
||||
if !ok {
|
||||
return fmt.Errorf("%s: Attribute '%s' not found", nameSecond, keySecond)
|
||||
if !(okFirst || okSecond) {
|
||||
// If they both don't exist then they are equally unset, so that's okay.
|
||||
return nil
|
||||
}
|
||||
|
||||
if vFirst != vSecond {
|
||||
|
|
|
@ -1175,3 +1175,154 @@ func TestCheckNoResourceAttr_empty(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTestCheckResourceAttrPair(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
state *terraform.State
|
||||
wantErr string
|
||||
}{
|
||||
"exist match": {
|
||||
&terraform.State{
|
||||
Modules: []*terraform.ModuleState{
|
||||
{
|
||||
Path: []string{"root"},
|
||||
Resources: map[string]*terraform.ResourceState{
|
||||
"test.a": {
|
||||
Primary: &terraform.InstanceState{
|
||||
Attributes: map[string]string{
|
||||
"a": "boop",
|
||||
},
|
||||
},
|
||||
},
|
||||
"test.b": {
|
||||
Primary: &terraform.InstanceState{
|
||||
Attributes: map[string]string{
|
||||
"b": "boop",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
``,
|
||||
},
|
||||
"nonexist match": {
|
||||
&terraform.State{
|
||||
Modules: []*terraform.ModuleState{
|
||||
{
|
||||
Path: []string{"root"},
|
||||
Resources: map[string]*terraform.ResourceState{
|
||||
"test.a": {
|
||||
Primary: &terraform.InstanceState{
|
||||
Attributes: map[string]string{},
|
||||
},
|
||||
},
|
||||
"test.b": {
|
||||
Primary: &terraform.InstanceState{
|
||||
Attributes: map[string]string{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
``,
|
||||
},
|
||||
"exist nonmatch": {
|
||||
&terraform.State{
|
||||
Modules: []*terraform.ModuleState{
|
||||
{
|
||||
Path: []string{"root"},
|
||||
Resources: map[string]*terraform.ResourceState{
|
||||
"test.a": {
|
||||
Primary: &terraform.InstanceState{
|
||||
Attributes: map[string]string{
|
||||
"a": "beep",
|
||||
},
|
||||
},
|
||||
},
|
||||
"test.b": {
|
||||
Primary: &terraform.InstanceState{
|
||||
Attributes: map[string]string{
|
||||
"b": "boop",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
`test.a: Attribute 'a' expected "boop", got "beep"`,
|
||||
},
|
||||
"inconsistent exist a": {
|
||||
&terraform.State{
|
||||
Modules: []*terraform.ModuleState{
|
||||
{
|
||||
Path: []string{"root"},
|
||||
Resources: map[string]*terraform.ResourceState{
|
||||
"test.a": {
|
||||
Primary: &terraform.InstanceState{
|
||||
Attributes: map[string]string{
|
||||
"a": "beep",
|
||||
},
|
||||
},
|
||||
},
|
||||
"test.b": {
|
||||
Primary: &terraform.InstanceState{
|
||||
Attributes: map[string]string{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
`test.a: Attribute "a" is "beep", but "b" is not set in test.b`,
|
||||
},
|
||||
"inconsistent exist b": {
|
||||
&terraform.State{
|
||||
Modules: []*terraform.ModuleState{
|
||||
{
|
||||
Path: []string{"root"},
|
||||
Resources: map[string]*terraform.ResourceState{
|
||||
"test.a": {
|
||||
Primary: &terraform.InstanceState{
|
||||
Attributes: map[string]string{},
|
||||
},
|
||||
},
|
||||
"test.b": {
|
||||
Primary: &terraform.InstanceState{
|
||||
Attributes: map[string]string{
|
||||
"b": "boop",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
`test.a: Attribute "a" not set, but "b" is set in test.b as "boop"`,
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
fn := TestCheckResourceAttrPair("test.a", "a", "test.b", "b")
|
||||
err := fn(test.state)
|
||||
|
||||
if test.wantErr != "" {
|
||||
if err == nil {
|
||||
t.Fatalf("succeeded; want error\nwant: %s", test.wantErr)
|
||||
}
|
||||
if got, want := err.Error(), test.wantErr; got != want {
|
||||
t.Fatalf("wrong error\ngot: %s\nwant: %s", got, want)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("failed; want success\ngot: %s", err.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue