Skip to content

Commit 738ea64

Browse files
Add performance config field to Filestore instance (#12245) (#20218)
[upstream:8ba278ec6b9c43e8d0a65211cc40d4d02168cb91] Signed-off-by: Modular Magician <[email protected]>
1 parent 5804f22 commit 738ea64

File tree

4 files changed

+383
-0
lines changed

4 files changed

+383
-0
lines changed

.changelog/12245.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
filestore: added `performance_config` field to `google_filestore_instance`
3+
```

google/services/filestore/resource_filestore_instance.go

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,57 @@ Please refer to the field 'effective_labels' for all of the labels present on th
256256
Description: `The name of the location of the instance. This can be a region for ENTERPRISE tier instances.`,
257257
ExactlyOneOf: []string{},
258258
},
259+
"performance_config": {
260+
Type: schema.TypeList,
261+
Optional: true,
262+
Description: `Performance configuration for the instance. If not provided,
263+
the default performance settings will be used.`,
264+
MaxItems: 1,
265+
Elem: &schema.Resource{
266+
Schema: map[string]*schema.Schema{
267+
"fixed_iops": {
268+
Type: schema.TypeList,
269+
Optional: true,
270+
Description: `The instance will have a fixed provisioned IOPS value,
271+
which will remain constant regardless of instance
272+
capacity.`,
273+
MaxItems: 1,
274+
Elem: &schema.Resource{
275+
Schema: map[string]*schema.Schema{
276+
"max_iops": {
277+
Type: schema.TypeInt,
278+
Optional: true,
279+
Description: `The number of IOPS to provision for the instance.
280+
max_iops must be in multiple of 1000.`,
281+
},
282+
},
283+
},
284+
ConflictsWith: []string{},
285+
},
286+
"iops_per_tb": {
287+
Type: schema.TypeList,
288+
Optional: true,
289+
Description: `The instance provisioned IOPS will change dynamically
290+
based on the capacity of the instance.`,
291+
MaxItems: 1,
292+
Elem: &schema.Resource{
293+
Schema: map[string]*schema.Schema{
294+
"max_iops_per_tb": {
295+
Type: schema.TypeInt,
296+
Optional: true,
297+
Description: `The instance max IOPS will be calculated by multiplying
298+
the capacity of the instance (TB) by max_iops_per_tb,
299+
and rounding to the nearest 1000. The instance max IOPS
300+
will be changed dynamically based on the instance
301+
capacity.`,
302+
},
303+
},
304+
},
305+
ConflictsWith: []string{},
306+
},
307+
},
308+
},
309+
},
259310
"protocol": {
260311
Type: schema.TypeString,
261312
Optional: true,
@@ -367,6 +418,12 @@ func resourceFilestoreInstanceCreate(d *schema.ResourceData, meta interface{}) e
367418
} else if v, ok := d.GetOkExists("deletion_protection_reason"); !tpgresource.IsEmptyValue(reflect.ValueOf(deletionProtectionReasonProp)) && (ok || !reflect.DeepEqual(v, deletionProtectionReasonProp)) {
368419
obj["deletionProtectionReason"] = deletionProtectionReasonProp
369420
}
421+
performanceConfigProp, err := expandFilestoreInstancePerformanceConfig(d.Get("performance_config"), d, config)
422+
if err != nil {
423+
return err
424+
} else if v, ok := d.GetOkExists("performance_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(performanceConfigProp)) && (ok || !reflect.DeepEqual(v, performanceConfigProp)) {
425+
obj["performanceConfig"] = performanceConfigProp
426+
}
370427
labelsProp, err := expandFilestoreInstanceEffectiveLabels(d.Get("effective_labels"), d, config)
371428
if err != nil {
372429
return err
@@ -534,6 +591,9 @@ func resourceFilestoreInstanceRead(d *schema.ResourceData, meta interface{}) err
534591
if err := d.Set("deletion_protection_reason", flattenFilestoreInstanceDeletionProtectionReason(res["deletionProtectionReason"], d, config)); err != nil {
535592
return fmt.Errorf("Error reading Instance: %s", err)
536593
}
594+
if err := d.Set("performance_config", flattenFilestoreInstancePerformanceConfig(res["performanceConfig"], d, config)); err != nil {
595+
return fmt.Errorf("Error reading Instance: %s", err)
596+
}
537597
if err := d.Set("terraform_labels", flattenFilestoreInstanceTerraformLabels(res["labels"], d, config)); err != nil {
538598
return fmt.Errorf("Error reading Instance: %s", err)
539599
}
@@ -584,6 +644,12 @@ func resourceFilestoreInstanceUpdate(d *schema.ResourceData, meta interface{}) e
584644
} else if v, ok := d.GetOkExists("deletion_protection_reason"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, deletionProtectionReasonProp)) {
585645
obj["deletionProtectionReason"] = deletionProtectionReasonProp
586646
}
647+
performanceConfigProp, err := expandFilestoreInstancePerformanceConfig(d.Get("performance_config"), d, config)
648+
if err != nil {
649+
return err
650+
} else if v, ok := d.GetOkExists("performance_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, performanceConfigProp)) {
651+
obj["performanceConfig"] = performanceConfigProp
652+
}
587653
labelsProp, err := expandFilestoreInstanceEffectiveLabels(d.Get("effective_labels"), d, config)
588654
if err != nil {
589655
return err
@@ -616,6 +682,10 @@ func resourceFilestoreInstanceUpdate(d *schema.ResourceData, meta interface{}) e
616682
updateMask = append(updateMask, "deletionProtectionReason")
617683
}
618684

685+
if d.HasChange("performance_config") {
686+
updateMask = append(updateMask, "performanceConfig")
687+
}
688+
619689
if d.HasChange("effective_labels") {
620690
updateMask = append(updateMask, "labels")
621691
}
@@ -951,6 +1021,81 @@ func flattenFilestoreInstanceDeletionProtectionReason(v interface{}, d *schema.R
9511021
return v
9521022
}
9531023

1024+
func flattenFilestoreInstancePerformanceConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1025+
if v == nil {
1026+
return nil
1027+
}
1028+
original := v.(map[string]interface{})
1029+
if len(original) == 0 {
1030+
return nil
1031+
}
1032+
transformed := make(map[string]interface{})
1033+
transformed["iops_per_tb"] =
1034+
flattenFilestoreInstancePerformanceConfigIopsPerTb(original["iopsPerTb"], d, config)
1035+
transformed["fixed_iops"] =
1036+
flattenFilestoreInstancePerformanceConfigFixedIops(original["fixedIops"], d, config)
1037+
return []interface{}{transformed}
1038+
}
1039+
func flattenFilestoreInstancePerformanceConfigIopsPerTb(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1040+
if v == nil {
1041+
return nil
1042+
}
1043+
original := v.(map[string]interface{})
1044+
if len(original) == 0 {
1045+
return nil
1046+
}
1047+
transformed := make(map[string]interface{})
1048+
transformed["max_iops_per_tb"] =
1049+
flattenFilestoreInstancePerformanceConfigIopsPerTbMaxIopsPerTb(original["maxIopsPerTb"], d, config)
1050+
return []interface{}{transformed}
1051+
}
1052+
func flattenFilestoreInstancePerformanceConfigIopsPerTbMaxIopsPerTb(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1053+
// Handles the string fixed64 format
1054+
if strVal, ok := v.(string); ok {
1055+
if intVal, err := tpgresource.StringToFixed64(strVal); err == nil {
1056+
return intVal
1057+
}
1058+
}
1059+
1060+
// number values are represented as float64
1061+
if floatVal, ok := v.(float64); ok {
1062+
intVal := int(floatVal)
1063+
return intVal
1064+
}
1065+
1066+
return v // let terraform core handle it otherwise
1067+
}
1068+
1069+
func flattenFilestoreInstancePerformanceConfigFixedIops(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1070+
if v == nil {
1071+
return nil
1072+
}
1073+
original := v.(map[string]interface{})
1074+
if len(original) == 0 {
1075+
return nil
1076+
}
1077+
transformed := make(map[string]interface{})
1078+
transformed["max_iops"] =
1079+
flattenFilestoreInstancePerformanceConfigFixedIopsMaxIops(original["maxIops"], d, config)
1080+
return []interface{}{transformed}
1081+
}
1082+
func flattenFilestoreInstancePerformanceConfigFixedIopsMaxIops(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1083+
// Handles the string fixed64 format
1084+
if strVal, ok := v.(string); ok {
1085+
if intVal, err := tpgresource.StringToFixed64(strVal); err == nil {
1086+
return intVal
1087+
}
1088+
}
1089+
1090+
// number values are represented as float64
1091+
if floatVal, ok := v.(float64); ok {
1092+
intVal := int(floatVal)
1093+
return intVal
1094+
}
1095+
1096+
return v // let terraform core handle it otherwise
1097+
}
1098+
9541099
func flattenFilestoreInstanceTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
9551100
if v == nil {
9561101
return v
@@ -1189,6 +1334,78 @@ func expandFilestoreInstanceDeletionProtectionReason(v interface{}, d tpgresourc
11891334
return v, nil
11901335
}
11911336

1337+
func expandFilestoreInstancePerformanceConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1338+
l := v.([]interface{})
1339+
if len(l) == 0 || l[0] == nil {
1340+
return nil, nil
1341+
}
1342+
raw := l[0]
1343+
original := raw.(map[string]interface{})
1344+
transformed := make(map[string]interface{})
1345+
1346+
transformedIopsPerTb, err := expandFilestoreInstancePerformanceConfigIopsPerTb(original["iops_per_tb"], d, config)
1347+
if err != nil {
1348+
return nil, err
1349+
} else if val := reflect.ValueOf(transformedIopsPerTb); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1350+
transformed["iopsPerTb"] = transformedIopsPerTb
1351+
}
1352+
1353+
transformedFixedIops, err := expandFilestoreInstancePerformanceConfigFixedIops(original["fixed_iops"], d, config)
1354+
if err != nil {
1355+
return nil, err
1356+
} else if val := reflect.ValueOf(transformedFixedIops); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1357+
transformed["fixedIops"] = transformedFixedIops
1358+
}
1359+
1360+
return transformed, nil
1361+
}
1362+
1363+
func expandFilestoreInstancePerformanceConfigIopsPerTb(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1364+
l := v.([]interface{})
1365+
if len(l) == 0 || l[0] == nil {
1366+
return nil, nil
1367+
}
1368+
raw := l[0]
1369+
original := raw.(map[string]interface{})
1370+
transformed := make(map[string]interface{})
1371+
1372+
transformedMaxIopsPerTb, err := expandFilestoreInstancePerformanceConfigIopsPerTbMaxIopsPerTb(original["max_iops_per_tb"], d, config)
1373+
if err != nil {
1374+
return nil, err
1375+
} else if val := reflect.ValueOf(transformedMaxIopsPerTb); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1376+
transformed["maxIopsPerTb"] = transformedMaxIopsPerTb
1377+
}
1378+
1379+
return transformed, nil
1380+
}
1381+
1382+
func expandFilestoreInstancePerformanceConfigIopsPerTbMaxIopsPerTb(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1383+
return v, nil
1384+
}
1385+
1386+
func expandFilestoreInstancePerformanceConfigFixedIops(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1387+
l := v.([]interface{})
1388+
if len(l) == 0 || l[0] == nil {
1389+
return nil, nil
1390+
}
1391+
raw := l[0]
1392+
original := raw.(map[string]interface{})
1393+
transformed := make(map[string]interface{})
1394+
1395+
transformedMaxIops, err := expandFilestoreInstancePerformanceConfigFixedIopsMaxIops(original["max_iops"], d, config)
1396+
if err != nil {
1397+
return nil, err
1398+
} else if val := reflect.ValueOf(transformedMaxIops); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1399+
transformed["maxIops"] = transformedMaxIops
1400+
}
1401+
1402+
return transformed, nil
1403+
}
1404+
1405+
func expandFilestoreInstancePerformanceConfigFixedIopsMaxIops(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1406+
return v, nil
1407+
}
1408+
11921409
func expandFilestoreInstanceEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
11931410
if v == nil {
11941411
return map[string]string{}, nil

google/services/filestore/resource_filestore_instance_test.go

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,3 +287,127 @@ resource "google_filestore_instance" "instance" {
287287
}
288288
`, name, location, tier, deletionProtection, deletionProtectionReason)
289289
}
290+
291+
func TestAccFilestoreInstance_performanceConfig(t *testing.T) {
292+
t.Parallel()
293+
294+
name := fmt.Sprintf("tf-test-%d", acctest.RandInt(t))
295+
location := "us-central1"
296+
tier := "REGIONAL"
297+
298+
acctest.VcrTest(t, resource.TestCase{
299+
PreCheck: func() { acctest.AccTestPreCheck(t) },
300+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
301+
CheckDestroy: testAccCheckFilestoreInstanceDestroyProducer(t),
302+
Steps: []resource.TestStep{
303+
{
304+
Config: testAccFilestoreInstance_fixedIopsPerformanceConfig(name, location, tier),
305+
Check: resource.ComposeTestCheckFunc(
306+
resource.TestCheckResourceAttr("google_filestore_instance.instance", "performance_config.0.fixed_iops.0.max_iops", "17000"),
307+
),
308+
},
309+
{
310+
ResourceName: "google_filestore_instance.instance",
311+
ImportState: true,
312+
ImportStateVerify: true,
313+
ImportStateVerifyIgnore: []string{"zone"},
314+
},
315+
{
316+
Config: testAccFilestoreInstance_iopsPerTbPerformanceConfig(name, location, tier),
317+
Check: resource.ComposeTestCheckFunc(
318+
resource.TestCheckResourceAttr("google_filestore_instance.instance", "performance_config.0.iops_per_tb.0.max_iops_per_tb", "17000"),
319+
),
320+
},
321+
{
322+
ResourceName: "google_filestore_instance.instance",
323+
ImportState: true,
324+
ImportStateVerify: true,
325+
ImportStateVerifyIgnore: []string{"zone"},
326+
},
327+
{
328+
Config: testAccFilestoreInstance_defaultConfig(name, location, tier),
329+
},
330+
{
331+
ResourceName: "google_filestore_instance.instance",
332+
ImportState: true,
333+
ImportStateVerify: true,
334+
ImportStateVerifyIgnore: []string{"zone"},
335+
},
336+
},
337+
})
338+
}
339+
340+
func testAccFilestoreInstance_fixedIopsPerformanceConfig(name, location, tier string) string {
341+
return fmt.Sprintf(`
342+
resource "google_filestore_instance" "instance" {
343+
name = "%s"
344+
location = "%s"
345+
tier = "%s"
346+
description = "An instance created during testing."
347+
348+
file_shares {
349+
capacity_gb = 1024
350+
name = "share"
351+
}
352+
353+
networks {
354+
network = "default"
355+
modes = ["MODE_IPV4"]
356+
}
357+
358+
performance_config {
359+
fixed_iops {
360+
max_iops = 17000
361+
}
362+
}
363+
}
364+
`, name, location, tier)
365+
}
366+
367+
func testAccFilestoreInstance_iopsPerTbPerformanceConfig(name, location, tier string) string {
368+
return fmt.Sprintf(`
369+
resource "google_filestore_instance" "instance" {
370+
name = "%s"
371+
zone = "%s"
372+
tier = "%s"
373+
description = "An instance created during testing."
374+
375+
file_shares {
376+
capacity_gb = 1024
377+
name = "share"
378+
}
379+
380+
networks {
381+
network = "default"
382+
modes = ["MODE_IPV4"]
383+
}
384+
385+
performance_config {
386+
iops_per_tb {
387+
max_iops_per_tb = 17000
388+
}
389+
}
390+
}
391+
`, name, location, tier)
392+
}
393+
394+
func testAccFilestoreInstance_defaultConfig(name, location, tier string) string {
395+
return fmt.Sprintf(`
396+
resource "google_filestore_instance" "instance" {
397+
name = "%s"
398+
zone = "%s"
399+
tier = "%s"
400+
description = "An instance created during testing."
401+
402+
file_shares {
403+
capacity_gb = 1024
404+
name = "share"
405+
}
406+
407+
networks {
408+
network = "default"
409+
modes = ["MODE_IPV4"]
410+
}
411+
}
412+
`, name, location, tier)
413+
}

0 commit comments

Comments
 (0)