Skip to content

Commit bc60933

Browse files
Deleted immutable attributes for initialUser and weeklySchedule so th… (#7552) (#14187)
* Deleted immutable attributes for initialUser and weeklySchedule so that deleting/adding these properties doesn't force new cluster creation * Automated tests for initialUser and automatedBackupPolicy * Add ImportStateVerifyIgnore for non-changing fields * gofmt fixes --------- Signed-off-by: Modular Magician <[email protected]> Co-authored-by: Stephen Lewis (Burrows) <[email protected]>
1 parent 1e1e541 commit bc60933

File tree

3 files changed

+164
-2
lines changed

3 files changed

+164
-2
lines changed

.changelog/7552.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
```release-note:bug
2+
AlloyDB: Deleted immutable flag for initalUser and weeklySchedule
3+
4+
```

google/resource_alloydb_cluster.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ If no policy is provided then the default policy will be used. The default polic
7070
Type: schema.TypeList,
7171
Computed: true,
7272
Optional: true,
73-
ForceNew: true,
7473
Description: `Weekly schedule for the Backup.`,
7574
MaxItems: 1,
7675
Elem: &schema.Resource{
@@ -186,7 +185,6 @@ A duration in seconds with up to nine fractional digits, terminated by 's'. Exam
186185
"initial_user": {
187186
Type: schema.TypeList,
188187
Optional: true,
189-
ForceNew: true,
190188
Description: `Initial user to setup during cluster creation.`,
191189
MaxItems: 1,
192190
Elem: &schema.Resource{
@@ -465,6 +463,12 @@ func resourceAlloydbClusterUpdate(d *schema.ResourceData, meta interface{}) erro
465463
} else if v, ok := d.GetOkExists("display_name"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, displayNameProp)) {
466464
obj["displayName"] = displayNameProp
467465
}
466+
initialUserProp, err := expandAlloydbClusterInitialUser(d.Get("initial_user"), d, config)
467+
if err != nil {
468+
return err
469+
} else if v, ok := d.GetOkExists("initial_user"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, initialUserProp)) {
470+
obj["initialUser"] = initialUserProp
471+
}
468472
automatedBackupPolicyProp, err := expandAlloydbClusterAutomatedBackupPolicy(d.Get("automated_backup_policy"), d, config)
469473
if err != nil {
470474
return err
@@ -492,6 +496,10 @@ func resourceAlloydbClusterUpdate(d *schema.ResourceData, meta interface{}) erro
492496
updateMask = append(updateMask, "displayName")
493497
}
494498

499+
if d.HasChange("initial_user") {
500+
updateMask = append(updateMask, "initialUser")
501+
}
502+
495503
if d.HasChange("automated_backup_policy") {
496504
updateMask = append(updateMask, "automatedBackupPolicy")
497505
}

google/resource_alloydb_cluster_test.go

+150
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,153 @@ resource "google_compute_network" "default" {
6767
}
6868
`, context)
6969
}
70+
71+
// Test if adding automatedBackupPolicy AND initialUser re-creates the cluster.
72+
// Ideally, cluster shouldn't be re-created. This test will only pass if the cluster
73+
// isn't re-created but updated in-place.
74+
func TestAccAlloydbCluster_addAutomatedBackupPolicyAndInitialUser(t *testing.T) {
75+
t.Parallel()
76+
77+
context := map[string]interface{}{
78+
"random_suffix": RandString(t, 10),
79+
}
80+
81+
VcrTest(t, resource.TestCase{
82+
PreCheck: func() { testAccPreCheck(t) },
83+
ProtoV5ProviderFactories: ProtoV5ProviderFactories(t),
84+
CheckDestroy: testAccCheckAlloydbClusterDestroyProducer(t),
85+
Steps: []resource.TestStep{
86+
{
87+
Config: testAccAlloydbCluster_withoutInitialUserAndAutomatedBackupPolicy(context),
88+
},
89+
{
90+
ResourceName: "google_alloydb_cluster.default",
91+
ImportState: true,
92+
ImportStateVerify: true,
93+
ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"},
94+
},
95+
{
96+
Config: testAccAlloydbCluster_withInitialUserAndAutomatedBackupPolicy(context),
97+
},
98+
{
99+
ResourceName: "google_alloydb_cluster.default",
100+
ImportState: true,
101+
ImportStateVerify: true,
102+
ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"},
103+
},
104+
{
105+
Config: testAccAlloydbCluster_alloydbClusterBasicExample(context),
106+
},
107+
},
108+
})
109+
}
110+
111+
// Test if deleting automatedBackupPolicy AND initialUser re-creates the cluster.
112+
// Ideally, cluster shouldn't be re-created. This test will only pass if the cluster
113+
// isn't re-created but updated in-place.
114+
func TestAccAlloydbCluster_deleteAutomatedBackupPolicyAndInitialUser(t *testing.T) {
115+
t.Parallel()
116+
117+
context := map[string]interface{}{
118+
"random_suffix": RandString(t, 10),
119+
}
120+
121+
VcrTest(t, resource.TestCase{
122+
PreCheck: func() { testAccPreCheck(t) },
123+
ProtoV5ProviderFactories: ProtoV5ProviderFactories(t),
124+
CheckDestroy: testAccCheckAlloydbClusterDestroyProducer(t),
125+
Steps: []resource.TestStep{
126+
{
127+
Config: testAccAlloydbCluster_withInitialUserAndAutomatedBackupPolicy(context),
128+
},
129+
{
130+
ResourceName: "google_alloydb_cluster.default",
131+
ImportState: true,
132+
ImportStateVerify: true,
133+
ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"},
134+
},
135+
{
136+
Config: testAccAlloydbCluster_withoutInitialUserAndAutomatedBackupPolicy(context),
137+
},
138+
{
139+
ResourceName: "google_alloydb_cluster.default",
140+
ImportState: true,
141+
ImportStateVerify: true,
142+
ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"},
143+
},
144+
{
145+
Config: testAccAlloydbCluster_alloydbClusterBasicExample(context),
146+
},
147+
},
148+
})
149+
}
150+
151+
func testAccAlloydbCluster_withInitialUserAndAutomatedBackupPolicy(context map[string]interface{}) string {
152+
return Nprintf(`
153+
resource "google_alloydb_cluster" "default" {
154+
cluster_id = "tf-test-alloydb-cluster%{random_suffix}"
155+
location = "us-central1"
156+
network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}"
157+
158+
initial_user {
159+
user = "tf-test-alloydb-cluster%{random_suffix}"
160+
password = "tf-test-alloydb-cluster%{random_suffix}"
161+
}
162+
163+
automated_backup_policy {
164+
location = "us-central1"
165+
backup_window = "1800s"
166+
enabled = true
167+
168+
weekly_schedule {
169+
days_of_week = ["MONDAY"]
170+
171+
start_times {
172+
hours = 23
173+
minutes = 0
174+
seconds = 0
175+
nanos = 0
176+
}
177+
}
178+
179+
quantity_based_retention {
180+
count = 1
181+
}
182+
183+
labels = {
184+
test = "tf-test-alloydb-cluster%{random_suffix}"
185+
}
186+
}
187+
lifecycle {
188+
prevent_destroy = true
189+
}
190+
}
191+
192+
data "google_project" "project" {
193+
}
194+
195+
resource "google_compute_network" "default" {
196+
name = "tf-test-alloydb-cluster%{random_suffix}"
197+
}
198+
`, context)
199+
}
200+
201+
func testAccAlloydbCluster_withoutInitialUserAndAutomatedBackupPolicy(context map[string]interface{}) string {
202+
return Nprintf(`
203+
resource "google_alloydb_cluster" "default" {
204+
cluster_id = "tf-test-alloydb-cluster%{random_suffix}"
205+
location = "us-central1"
206+
network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}"
207+
lifecycle {
208+
prevent_destroy = true
209+
}
210+
}
211+
212+
data "google_project" "project" {
213+
}
214+
215+
resource "google_compute_network" "default" {
216+
name = "tf-test-alloydb-cluster%{random_suffix}"
217+
}
218+
`, context)
219+
}

0 commit comments

Comments
 (0)