Skip to content

Commit 2847ec6

Browse files
Terraform Team Automationsagarp337
authored andcommitted
Bug Fix - Edit Volume ID inside a VolumeGroup results the VG gets destoried
1 parent 55922e9 commit 2847ec6

File tree

4 files changed

+99
-3
lines changed

4 files changed

+99
-3
lines changed

internal/integrationtest/core_volume_group_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ var (
5050
"backup_policy_id": acctest.Representation{RepType: acctest.Optional, Create: `${data.oci_core_volume_backup_policies.test_volume_user_defined_backup_policies.volume_backup_policies.0.id}`},
5151
"defined_tags": acctest.Representation{RepType: acctest.Optional, Create: `${map("${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}", "value")}`, Update: `${map("${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}", "updatedValue")}`},
5252
"display_name": acctest.Representation{RepType: acctest.Optional, Create: `displayName`, Update: `displayName2`},
53+
"volume_ids": acctest.Representation{RepType: acctest.Optional, Create: nil, Update: []string{`${oci_core_volume.source_volume_list.*.id[0]}`}},
5354
"freeform_tags": acctest.Representation{RepType: acctest.Optional, Create: map[string]string{"Department": "Finance"}, Update: map[string]string{"Department": "Accounting"}},
5455
}
5556
CoreVolumeGroupSourceDetailsRepresentation = map[string]interface{}{
@@ -227,7 +228,7 @@ func TestCoreVolumeGroupResource_basic(t *testing.T) {
227228
resource.TestCheckResourceAttr(resourceName, "source_details.#", "1"),
228229
resource.TestCheckResourceAttr(resourceName, "source_details.0.type", "volumeIds"),
229230
resource.TestCheckResourceAttrSet(resourceName, "time_created"),
230-
resource.TestCheckResourceAttr(resourceName, "volume_ids.#", "2"),
231+
resource.TestCheckResourceAttr(resourceName, "volume_ids.#", "1"),
231232

232233
func(s *terraform.State) (err error) {
233234
resId2, err = acctest.FromInstanceState(s, resourceName, "id")

internal/service/core/core_volume_group_resource.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,12 @@ func CoreVolumeGroupResource() *schema.Resource {
179179
Computed: true,
180180
},
181181
"volume_ids": {
182-
Type: schema.TypeList,
183-
Computed: true,
182+
Type: schema.TypeList,
183+
Optional: true,
184+
Computed: true,
185+
MaxItems: 64,
186+
MinItems: 0,
187+
DiffSuppressFunc: tfresource.ListEqualIgnoreOrderSuppressDiff,
184188
Elem: &schema.Schema{
185189
Type: schema.TypeString,
186190
},
@@ -303,6 +307,12 @@ func (s *CoreVolumeGroupResourceCrud) Create() error {
303307
}
304308
}
305309

310+
if volumeIds, ok := s.D.GetOkExists("volume_ids"); ok {
311+
if tmp := volumeIds.([]interface{}); len(tmp) > 0 {
312+
return fmt.Errorf("volume_ids under resource is not supported during creation")
313+
}
314+
}
315+
306316
if volumeGroupReplicas, ok := s.D.GetOkExists("volume_group_replicas"); ok {
307317
interfaces := volumeGroupReplicas.([]interface{})
308318
tmp := make([]oci_core.VolumeGroupReplicaDetails, len(interfaces))
@@ -403,14 +413,17 @@ func (s *CoreVolumeGroupResourceCrud) Update() error {
403413
}
404414
}
405415

416+
// Indicate if current update is disabling volume group replica
406417
disableReplication := false
407418
if volumeGroupReplicasDeletion, ok := s.D.GetOkExists("volume_group_replicas_deletion"); ok {
408419
disableReplication = volumeGroupReplicasDeletion.(bool)
409420
if disableReplication == true {
410421
request.VolumeGroupReplicas = []oci_core.VolumeGroupReplicaDetails{}
411422
}
423+
disableReplication = s.D.HasChange("volume_group_replicas_deletion") && disableReplication
412424
}
413425

426+
// We don't want customers to disable volume group replica and update volume list at the same time
414427
if !disableReplication {
415428
if volumeIds, ok := s.D.GetOkExists("volume_ids"); ok {
416429
interfaces := volumeIds.([]interface{})

internal/tfresource/crud_helpers.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,38 @@ func loadBalancersSuppressDiff(d schemaResourceData) bool {
527527
func EqualIgnoreCaseSuppressDiff(key string, old string, new string, d *schema.ResourceData) bool {
528528
return strings.EqualFold(old, new)
529529
}
530+
func ListEqualIgnoreOrderSuppressDiff(key string, old string, new string, d *schema.ResourceData) bool {
531+
return listEqualIgnoreOrderSuppressDiff(key, d)
532+
}
533+
534+
func listEqualIgnoreOrderSuppressDiff(key string, d schemaResourceData) bool {
535+
// Take only the field name, key might be field.#
536+
oldRaw, newRaw := d.GetChange(strings.Split(key, ".")[0])
537+
if newRaw == nil || oldRaw == nil {
538+
return false
539+
}
540+
oldList := oldRaw.([]interface{})
541+
newList := newRaw.([]interface{})
542+
543+
if len(oldList) != len(newList) {
544+
return false
545+
}
546+
tmp1 := make([]string, len(oldList))
547+
tmp2 := make([]string, len(newList))
548+
549+
for i := range oldList {
550+
tmp1[i] = oldList[i].(string)
551+
tmp2[i] = newList[i].(string)
552+
}
553+
sort.Strings(tmp1)
554+
sort.Strings(tmp2)
555+
for i := range oldList {
556+
if tmp1[i] != tmp2[i] {
557+
return false
558+
}
559+
}
560+
return true
561+
}
530562

531563
func FieldDeprecatedAndAvoidReferences(deprecatedFieldName string) string {
532564
return fmt.Sprintf("The '%s' field has been deprecated and may be removed in a future version. Do not use this field.", deprecatedFieldName)

internal/tfresource/crud_helpers_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,15 @@ func (d *mockResourceData) GetChange(_ string) (interface{}, interface{}) {
248248
if d.state == "3" {
249249
return []interface{}{map[string]interface{}{"load_balancer_id": "1"}}, []interface{}{map[string]interface{}{"load_balancer_id": "2"}}
250250
}
251+
if d.state == "4" {
252+
return []interface{}{"foo", "bar"}, []interface{}{"bar", "foo"}
253+
}
254+
if d.state == "5" {
255+
return []interface{}{"foo", "foo", "bar"}, []interface{}{"bar", "bar", "foo"}
256+
}
257+
if d.state == "6" {
258+
return []interface{}{"foo", "bar"}, []interface{}{"foo"}
259+
}
251260
return []interface{}{map[string]interface{}{"load_balancer_id": "1"}}, []interface{}{map[string]interface{}{"load_balancer_id": "1"}}
252261
}
253262

@@ -613,6 +622,47 @@ func TestUnitGetTimeoutDuration(t *testing.T) {
613622
}
614623
}
615624

625+
func TestListEqualIgnoreOrderSuppressDiff(t *testing.T) {
626+
type args struct {
627+
d *mockResourceData
628+
}
629+
type testFormat struct {
630+
name string
631+
args args
632+
output bool
633+
}
634+
changeReqResourceData := func(k string) *mockResourceData {
635+
reqResourceData := &mockResourceData{
636+
state: k,
637+
}
638+
return reqResourceData
639+
}
640+
tests := []testFormat{
641+
{
642+
name: "Test same lists with diff order",
643+
args: args{d: changeReqResourceData("4")},
644+
output: true,
645+
},
646+
{
647+
name: "Test diff lists with duplicated elements",
648+
args: args{d: changeReqResourceData("5")},
649+
output: false,
650+
},
651+
{
652+
name: "Test diff lists with diff length",
653+
args: args{d: changeReqResourceData("6")},
654+
output: false,
655+
},
656+
}
657+
for _, test := range tests {
658+
t.Logf("Running %s", test.name)
659+
t.Logf("Running %s", fmt.Sprint(test.args.d))
660+
if res := listEqualIgnoreOrderSuppressDiff("volume_id", test.args.d); res != test.output {
661+
t.Errorf("Output %t not equal to expected %t", res, test.output)
662+
}
663+
}
664+
}
665+
616666
func TestUnitGenericMapToJsonMap(t *testing.T) {
617667
type args struct {
618668
genericMap map[string]interface{}

0 commit comments

Comments
 (0)