Skip to content

Commit 3f61149

Browse files
modular-magiciandanawillow
authored andcommitted
allow going from no ip_allocation_policy to a blank-equivalent one (#3723)
Signed-off-by: Modular Magician <[email protected]>
1 parent 34c8d97 commit 3f61149

File tree

4 files changed

+119
-0
lines changed

4 files changed

+119
-0
lines changed

google/resource_container_cluster.go

+33
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package google
33
import (
44
"fmt"
55
"log"
6+
"reflect"
67
"regexp"
78
"strings"
89
"time"
@@ -53,6 +54,8 @@ func resourceContainerCluster() *schema.Resource {
5354
Update: resourceContainerClusterUpdate,
5455
Delete: resourceContainerClusterDelete,
5556

57+
CustomizeDiff: resourceContainerClusterIpAllocationCustomizeDiff,
58+
5659
Timeouts: &schema.ResourceTimeout{
5760
Create: schema.DefaultTimeout(30 * time.Minute),
5861
Update: schema.DefaultTimeout(30 * time.Minute),
@@ -619,6 +622,36 @@ func resourceContainerCluster() *schema.Resource {
619622
}
620623
}
621624

625+
func resourceContainerClusterIpAllocationCustomizeDiff(diff *schema.ResourceDiff, meta interface{}) error {
626+
// separate func to allow unit testing
627+
return resourceContainerClusterIpAllocationCustomizeDiffFunc(diff)
628+
}
629+
630+
func resourceContainerClusterIpAllocationCustomizeDiffFunc(diff TerraformResourceDiff) error {
631+
o, n := diff.GetChange("ip_allocation_policy")
632+
633+
oList := o.([]interface{})
634+
nList := n.([]interface{})
635+
if len(oList) > 0 || len(nList) == 0 {
636+
// we only care about going from unset to set, so return early if the field was set before
637+
// or is unset now
638+
return nil
639+
}
640+
641+
// Unset is equivalent to a block where all the values are zero
642+
// This might change if use_ip_aliases ends up defaulting to true server-side.
643+
// The console says it will eventually, but it's unclear whether that's in the API
644+
// too or just client code.
645+
polMap := nList[0].(map[string]interface{})
646+
for _, v := range polMap {
647+
if !isEmptyValue(reflect.ValueOf(v)) {
648+
// found a non-empty value, so continue with the diff as it was
649+
return nil
650+
}
651+
}
652+
return diff.Clear("ip_allocation_policy")
653+
}
654+
622655
func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) error {
623656
config := meta.(*Config)
624657

google/resource_container_cluster_test.go

+63
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,69 @@ import (
1212
"github.com/hashicorp/terraform/terraform"
1313
)
1414

15+
func TestContainerClusterIpAllocationCustomizeDiff(t *testing.T) {
16+
t.Parallel()
17+
18+
cases := map[string]struct {
19+
BeforePolicy []interface{}
20+
AfterPolicy []interface{}
21+
ExpectDiffCleared bool
22+
}{
23+
"empty to false value": {
24+
BeforePolicy: []interface{}{},
25+
AfterPolicy: []interface{}{
26+
map[string]interface{}{
27+
"use_ip_aliases": false,
28+
},
29+
},
30+
ExpectDiffCleared: true,
31+
},
32+
"empty to true value": {
33+
BeforePolicy: []interface{}{},
34+
AfterPolicy: []interface{}{
35+
map[string]interface{}{
36+
"use_ip_aliases": true,
37+
},
38+
},
39+
ExpectDiffCleared: false,
40+
},
41+
"empty to empty": {
42+
BeforePolicy: []interface{}{},
43+
AfterPolicy: []interface{}{},
44+
ExpectDiffCleared: false,
45+
},
46+
"non-empty to non-empty": {
47+
BeforePolicy: []interface{}{
48+
map[string]interface{}{
49+
"use_ip_aliases": false,
50+
},
51+
},
52+
AfterPolicy: []interface{}{
53+
map[string]interface{}{
54+
"use_ip_aliases": false,
55+
},
56+
},
57+
},
58+
}
59+
60+
for tn, tc := range cases {
61+
d := &ResourceDiffMock{
62+
Before: map[string]interface{}{
63+
"ip_allocation_policy": tc.BeforePolicy,
64+
},
65+
After: map[string]interface{}{
66+
"ip_allocation_policy": tc.AfterPolicy,
67+
},
68+
}
69+
if err := resourceContainerClusterIpAllocationCustomizeDiffFunc(d); err != nil {
70+
t.Errorf("%s failed, error calculating diff: %s", tn, err)
71+
}
72+
if _, ok := d.Cleared["ip_allocation_policy"]; ok != tc.ExpectDiffCleared {
73+
t.Errorf("%s failed, expected cleared to be %v, was %v", tn, tc.ExpectDiffCleared, ok)
74+
}
75+
}
76+
}
77+
1578
func TestAccContainerCluster_basic(t *testing.T) {
1679
t.Parallel()
1780

google/test_utils.go

+18
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,24 @@ func (d *ResourceDataMock) Id() string {
6262
return d.id
6363
}
6464

65+
type ResourceDiffMock struct {
66+
Before map[string]interface{}
67+
After map[string]interface{}
68+
Cleared map[string]struct{}
69+
}
70+
71+
func (d *ResourceDiffMock) GetChange(key string) (interface{}, interface{}) {
72+
return d.Before[key], d.After[key]
73+
}
74+
75+
func (d *ResourceDiffMock) Clear(key string) error {
76+
if d.Cleared == nil {
77+
d.Cleared = map[string]struct{}{}
78+
}
79+
d.Cleared[key] = struct{}{}
80+
return nil
81+
}
82+
6583
func toBool(attribute string) (bool, error) {
6684
// Handle the case where an unset value defaults to false
6785
if attribute == "" {

google/utils.go

+5
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ type TerraformResourceData interface {
2727
Id() string
2828
}
2929

30+
type TerraformResourceDiff interface {
31+
GetChange(string) (interface{}, interface{})
32+
Clear(string) error
33+
}
34+
3035
// getRegionFromZone returns the region from a zone for Google cloud.
3136
func getRegionFromZone(zone string) string {
3237
if zone != "" && len(zone) > 2 {

0 commit comments

Comments
 (0)