diff --git a/go.mod b/go.mod index 866a36b6f7..7e453323d2 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/terraform-providers/terraform-provider-aws v1.60.1-0.20210625132053-af2d5c0ad54f go.mongodb.org/atlas v0.21.0 go.mongodb.org/realm v0.1.0 + golang.org/x/exp v0.0.0-20221208152030-732eee02a75a ) require ( @@ -111,16 +112,16 @@ require ( github.com/vmihailenco/tagparser v0.1.1 // indirect github.com/zclconf/go-cty v1.12.1 // indirect go.opencensus.io v0.23.0 // indirect - golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167 // indirect + golang.org/x/crypto v0.1.0 // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/mod v0.4.2 // indirect - golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect + golang.org/x/mod v0.6.0 // indirect + golang.org/x/net v0.1.0 // indirect golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c // indirect - golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e // indirect - golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect - golang.org/x/text v0.3.7 // indirect + golang.org/x/sys v0.1.0 // indirect + golang.org/x/term v0.1.0 // indirect + golang.org/x/text v0.4.0 // indirect golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect - golang.org/x/tools v0.1.3 // indirect + golang.org/x/tools v0.2.0 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/api v0.48.0 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/go.sum b/go.sum index f2f150a18d..fa944f827c 100644 --- a/go.sum +++ b/go.sum @@ -963,6 +963,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167 h1:O8uGbHCqlTp2P6QJSLmCojM4mN6UemYv8K+dCnmHmu0= golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -974,6 +976,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= +golang.org/x/exp v0.0.0-20221208152030-732eee02a75a h1:4iLhBPcpqFmylhnkbY3W0ONLUYYkDAW9xMFLfxgsvCw= +golang.org/x/exp v0.0.0-20221208152030-732eee02a75a/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1001,6 +1005,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1057,6 +1063,8 @@ golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1164,9 +1172,13 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e h1:w36l2Uw3dRan1K3TyXriXvY+6T56GNmlKGcqiQUJDfM= golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1177,6 +1189,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1283,6 +1297,8 @@ golang.org/x/tools v0.1.2-0.20210512205948-8287d5da45e4/go.mod h1:o0xws9oXOQQZyj golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3 h1:L69ShwSZEyCsLKoAxDKeMvLDZkumEe8gXUZAjab0tX8= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/mongodbatlas/resource_mongodbatlas_advanced_cluster.go b/mongodbatlas/resource_mongodbatlas_advanced_cluster.go index b82ebe0213..4c5d73f61d 100644 --- a/mongodbatlas/resource_mongodbatlas_advanced_cluster.go +++ b/mongodbatlas/resource_mongodbatlas_advanced_cluster.go @@ -19,6 +19,7 @@ import ( "github.com/mwielbut/pointy" "github.com/spf13/cast" matlas "go.mongodb.org/atlas/mongodbatlas" + "golang.org/x/exp/slices" ) type acCtxKey string @@ -182,7 +183,7 @@ func resourceMongoDBAtlasAdvancedCluster() *schema.Resource { Computed: true, }, "replication_specs": { - Type: schema.TypeSet, + Type: schema.TypeList, Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -197,7 +198,7 @@ func resourceMongoDBAtlasAdvancedCluster() *schema.Resource { ValidateFunc: validation.IntBetween(1, 50), }, "region_configs": { - Type: schema.TypeSet, + Type: schema.TypeList, Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -307,7 +308,7 @@ func resourceMongoDBAtlasAdvancedCluster() *schema.Resource { }, }, }, - Set: replicationSpecsHashSet, + // Set: replicationSpecsHashSet, }, "root_cert_type": { Type: schema.TypeString, @@ -376,7 +377,7 @@ func resourceMongoDBAtlasAdvancedClusterCreate(ctx context.Context, d *schema.Re request := &matlas.AdvancedCluster{ Name: d.Get("name").(string), ClusterType: cast.ToString(d.Get("cluster_type")), - ReplicationSpecs: expandAdvancedReplicationSpecs(d.Get("replication_specs").(*schema.Set).List()), + ReplicationSpecs: expandAdvancedReplicationSpecs(d.Get("replication_specs").([]interface{})), } if v, ok := d.GetOk("backup_enabled"); ok { @@ -569,7 +570,7 @@ func resourceMongoDBAtlasAdvancedClusterRead(ctx context.Context, d *schema.Reso return diag.FromErr(fmt.Errorf(errorClusterAdvancedSetting, "pit_enabled", clusterName, err)) } - replicationSpecs, err := flattenAdvancedReplicationSpecs(ctx, cluster.ReplicationSpecs, d.Get("replication_specs").(*schema.Set).List(), d, conn) + replicationSpecs, err := flattenAdvancedReplicationSpecs(ctx, cluster.ReplicationSpecs, d.Get("replication_specs").([]interface{}), d, conn) if err != nil { return diag.FromErr(fmt.Errorf(errorClusterAdvancedSetting, "replication_specs", clusterName, err)) } @@ -695,7 +696,7 @@ func resourceMongoDBAtlasAdvancedClusterUpdate(ctx context.Context, d *schema.Re } if d.HasChange("replication_specs") { - cluster.ReplicationSpecs = expandAdvancedReplicationSpecs(d.Get("replication_specs").(*schema.Set).List()) + cluster.ReplicationSpecs = expandAdvancedReplicationSpecs(d.Get("replication_specs").([]interface{})) } if d.HasChange("root_cert_type") { @@ -854,7 +855,7 @@ func expandAdvancedReplicationSpec(tfMap map[string]interface{}) *matlas.Advance apiObject := &matlas.AdvancedReplicationSpec{ NumShards: tfMap["num_shards"].(int), ZoneName: tfMap["zone_name"].(string), - RegionConfigs: expandRegionConfigs(tfMap["region_configs"].(*schema.Set).List()), + RegionConfigs: expandRegionConfigs(tfMap["region_configs"].([]interface{})), } return apiObject @@ -1008,7 +1009,7 @@ func flattenAdvancedReplicationSpec(ctx context.Context, apiObject *matlas.Advan tfMap["num_shards"] = apiObject.NumShards tfMap["id"] = apiObject.ID if tfMapObject != nil { - object, containerIds, err := flattenAdvancedReplicationSpecRegionConfigs(ctx, apiObject.RegionConfigs, tfMapObject["region_configs"].(*schema.Set).List(), d, conn) + object, containerIds, err := flattenAdvancedReplicationSpecRegionConfigs(ctx, apiObject.RegionConfigs, tfMapObject["region_configs"].([]interface{}), d, conn) if err != nil { return nil, err } @@ -1027,30 +1028,75 @@ func flattenAdvancedReplicationSpec(ctx context.Context, apiObject *matlas.Advan return tfMap, nil } -func flattenAdvancedReplicationSpecs(ctx context.Context, apiObjects []*matlas.AdvancedReplicationSpec, tfMapObjects []interface{}, +func doesAdvancedReplicationSpecMatchAPI(tfObject map[string]interface{}, apiObject *matlas.AdvancedReplicationSpec) bool { + return tfObject["id"] == apiObject.ID || (tfObject["id"] == nil && tfObject["zone_name"] == apiObject.ZoneName) +} + +func flattenAdvancedReplicationSpecs(ctx context.Context, rawAPIObjects []*matlas.AdvancedReplicationSpec, tfMapObjects []interface{}, d *schema.ResourceData, conn *matlas.Client) ([]map[string]interface{}, error) { + var apiObjects []*matlas.AdvancedReplicationSpec + + for _, advancedReplicationSpec := range rawAPIObjects { + if advancedReplicationSpec != nil { + apiObjects = append(apiObjects, advancedReplicationSpec) + } + } + if len(apiObjects) == 0 { return nil, nil } - var tfList []map[string]interface{} + tfList := make([]map[string]interface{}, len(apiObjects)) + wasAPIObjectUsed := make([]bool, len(apiObjects)) - for i, apiObject := range apiObjects { - if apiObject == nil { - continue + for i := 0; i < len(tfList); i++ { + var tfMapObject map[string]interface{} + + if len(tfMapObjects) > i { + tfMapObject = tfMapObjects[i].(map[string]interface{}) } + for j := 0; j < len(apiObjects); j++ { + if wasAPIObjectUsed[j] { + continue + } + + if !doesAdvancedReplicationSpecMatchAPI(tfMapObject, apiObjects[j]) { + continue + } + + advancedReplicationSpec, err := flattenAdvancedReplicationSpec(ctx, apiObjects[j], tfMapObject, d, conn) + + if err != nil { + return nil, err + } + + tfList[i] = advancedReplicationSpec + wasAPIObjectUsed[j] = true + break + } + } + + for i, tfo := range tfList { var tfMapObject map[string]interface{} + if tfo != nil { + continue + } + if len(tfMapObjects) > i { tfMapObject = tfMapObjects[i].(map[string]interface{}) } - advancedReplicationSpec, err := flattenAdvancedReplicationSpec(ctx, apiObject, tfMapObject, d, conn) + j := slices.IndexFunc(wasAPIObjectUsed, func(isUsed bool) bool { return !isUsed }) + advancedReplicationSpec, err := flattenAdvancedReplicationSpec(ctx, apiObjects[j], tfMapObject, d, conn) + if err != nil { return nil, err } - tfList = append(tfList, advancedReplicationSpec) + + tfList[i] = advancedReplicationSpec + wasAPIObjectUsed[j] = true } return tfList, nil @@ -1259,7 +1305,7 @@ func replicationSpecsHashSet(v interface{}) int { var buf bytes.Buffer m := v.(map[string]interface{}) buf.WriteString(fmt.Sprintf("%d", m["num_shards"].(int))) - buf.WriteString(fmt.Sprintf("%+v", m["region_configs"].(*schema.Set))) + buf.WriteString(fmt.Sprintf("%+v", m["region_configs"].([]interface{}))) buf.WriteString(m["zone_name"].(string)) return schema.HashString(buf.String()) } @@ -1270,8 +1316,8 @@ func getUpgradeRequest(d *schema.ResourceData) *matlas.Cluster { } cs, us := d.GetChange("replication_specs") - currentSpecs := expandAdvancedReplicationSpecs(cs.(*schema.Set).List()) - updatedSpecs := expandAdvancedReplicationSpecs(us.(*schema.Set).List()) + currentSpecs := expandAdvancedReplicationSpecs(cs.([]interface{})) + updatedSpecs := expandAdvancedReplicationSpecs(us.([]interface{})) if len(currentSpecs) != 1 || len(updatedSpecs) != 1 || len(currentSpecs[0].RegionConfigs) != 1 || len(updatedSpecs[0].RegionConfigs) != 1 { return nil diff --git a/mongodbatlas/resource_mongodbatlas_advanced_cluster_migration_test.go b/mongodbatlas/resource_mongodbatlas_advanced_cluster_migration_test.go index aaa6961af8..dfd4082294 100644 --- a/mongodbatlas/resource_mongodbatlas_advanced_cluster_migration_test.go +++ b/mongodbatlas/resource_mongodbatlas_advanced_cluster_migration_test.go @@ -58,3 +58,75 @@ func TestAccClusterRSAdvancedClusterMigrateState_empty_advancedConfig(t *testing return } } + +func TestAccClusterRSAdvancedClusterV0StateUpgrade_ReplicationSpecs(t *testing.T) { + v0State := map[string]interface{}{ + "project_id": "test-id", + "name": "test-cluster", + "cluster_type": "REPLICASET", + "backup_enabled": true, + "disk_size_gb": 256, + "replication_specs": []interface{}{ + map[string]interface{}{ + "zone_name": "Test Zone", + "region_configs": []interface{}{ + map[string]interface{}{ + "priority": 7, + "provider_name": "AWS", + "region_name": "US_EAST_1", + "electable_specs": []interface{}{ + map[string]interface{}{ + "instance_size": "M30", + "node_count": 3, + }, + }, + "read_only_specs": []interface{}{ + map[string]interface{}{ + "disk_iops": 0, + "instance_size": "M30", + "node_count": 0, + }, + }, + "auto_scaling": []interface{}{ + map[string]interface{}{ + "compute_enabled": true, + "compute_max_instance_size": "M60", + "compute_min_instance_size": "M30", + "compute_scale_down_enabled": true, + "disk_gb_enabled": false, + }, + }, + }, + }, + }, + }, + } + + v0Config := terraform.NewResourceConfigRaw(v0State) + diags := resourceMongoDBAtlasAdvancedClusterResourceV0().Validate(v0Config) + + if len(diags) > 0 { + fmt.Println(diags) + t.Error("test precondition failed - invalid mongodb cluster v0 config") + + return + } + + // test migrate function + v1State := migrateBIConnectorConfig(v0State) + + v1Config := terraform.NewResourceConfigRaw(v1State) + diags = resourceMongoDBAtlasAdvancedCluster().Validate(v1Config) + if len(diags) > 0 { + fmt.Println(diags) + t.Error("migrated advanced cluster replication_specs invalid") + + return + } + + if len(v1State["replication_specs"].([]interface{})) != len(v0State["replication_specs"].([]interface{})) { + t.Error("migrated replication specs did not contain the same number of elements") + + return + } +}