Skip to content

Commit 735f2f1

Browse files
Filestore enterprise support (#5450) (#10662)
* Move tier to string * Add note on possible values * Add note for beta-only on enterprise * Starting to move to location * Add precreate * Write state migration * Use location in examples * Use upgrade state function instead of migrate * Fix linter * Update validator test to use location * Update TFV test config to use location Signed-off-by: Modular Magician <[email protected]>
1 parent b72a300 commit 735f2f1

6 files changed

+319
-51
lines changed

.changelog/5450.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
```release-note:enhancement
2+
filestore: added support for `ENTERPRISE` value on `google_filestore_instance` `tier`
3+
```
4+
```release-note:deprecation
5+
filestore: deprecated `zone` on `google_filestore_instance` in favor of `location` to allow for regional instances
6+
```

google/resource_filestore_instance.go

+248-22
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package google
1616

1717
import (
18+
"context"
1819
"fmt"
1920
"log"
2021
"reflect"
@@ -43,6 +44,15 @@ func resourceFilestoreInstance() *schema.Resource {
4344
Delete: schema.DefaultTimeout(6 * time.Minute),
4445
},
4546

47+
SchemaVersion: 1,
48+
StateUpgraders: []schema.StateUpgrader{
49+
{
50+
Type: resourceFilestoreInstanceResourceV0().CoreConfigSchema().ImpliedType(),
51+
Upgrade: resourceFilestoreInstanceUpgradeV0,
52+
Version: 0,
53+
},
54+
},
55+
4656
Schema: map[string]*schema.Schema{
4757
"file_shares": {
4858
Type: schema.TypeList,
@@ -119,17 +129,11 @@ addresses reserved for this instance.`,
119129
},
120130
},
121131
"tier": {
122-
Type: schema.TypeString,
123-
Required: true,
124-
ForceNew: true,
125-
ValidateFunc: validation.StringInSlice([]string{"TIER_UNSPECIFIED", "STANDARD", "PREMIUM", "BASIC_HDD", "BASIC_SSD", "HIGH_SCALE_SSD"}, false),
126-
Description: `The service tier of the instance. Possible values: ["TIER_UNSPECIFIED", "STANDARD", "PREMIUM", "BASIC_HDD", "BASIC_SSD", "HIGH_SCALE_SSD"]`,
127-
},
128-
"zone": {
129-
Type: schema.TypeString,
130-
Required: true,
131-
ForceNew: true,
132-
Description: `The name of the Filestore zone of the instance.`,
132+
Type: schema.TypeString,
133+
Required: true,
134+
ForceNew: true,
135+
Description: `The service tier of the instance.
136+
Possible values include: STANDARD, PREMIUM, BASIC_HDD, BASIC_SSD, HIGH_SCALE_SSD and ENTERPRISE (beta only)`,
133137
},
134138
"description": {
135139
Type: schema.TypeString,
@@ -142,6 +146,23 @@ addresses reserved for this instance.`,
142146
Description: `Resource labels to represent user-provided metadata.`,
143147
Elem: &schema.Schema{Type: schema.TypeString},
144148
},
149+
"location": {
150+
Type: schema.TypeString,
151+
Computed: true,
152+
Optional: true,
153+
ForceNew: true,
154+
Description: `The name of the location of the instance. This can be a region for ENTERPRISE tier instances.`,
155+
ExactlyOneOf: []string{},
156+
},
157+
"zone": {
158+
Type: schema.TypeString,
159+
Computed: true,
160+
Optional: true,
161+
Deprecated: "Deprecated in favor of location.",
162+
ForceNew: true,
163+
Description: `The name of the Filestore zone of the instance.`,
164+
ExactlyOneOf: []string{},
165+
},
145166
"create_time": {
146167
Type: schema.TypeString,
147168
Computed: true,
@@ -210,7 +231,7 @@ func resourceFilestoreInstanceCreate(d *schema.ResourceData, meta interface{}) e
210231
mutexKV.Lock(lockName)
211232
defer mutexKV.Unlock(lockName)
212233

213-
url, err := replaceVars(d, config, "{{FilestoreBasePath}}projects/{{project}}/locations/{{zone}}/instances?instanceId={{name}}")
234+
url, err := replaceVars(d, config, "{{FilestoreBasePath}}projects/{{project}}/locations/{{location}}/instances?instanceId={{name}}")
214235
if err != nil {
215236
return err
216237
}
@@ -229,13 +250,30 @@ func resourceFilestoreInstanceCreate(d *schema.ResourceData, meta interface{}) e
229250
billingProject = bp
230251
}
231252

253+
if d.Get("location") == "" {
254+
zone, err := getZone(d, config)
255+
if err != nil {
256+
return err
257+
}
258+
err = d.Set("location", zone)
259+
if err != nil {
260+
return err
261+
}
262+
}
263+
if strings.Contains(url, "locations//") {
264+
// re-compute url now that location must be set
265+
url, err = replaceVars(d, config, "{{FilestoreBasePath}}projects/{{project}}/locations/{{location}}/instances?instanceId={{name}}")
266+
if err != nil {
267+
return err
268+
}
269+
}
232270
res, err := sendRequestWithTimeout(config, "POST", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutCreate), isNotFilestoreQuotaError)
233271
if err != nil {
234272
return fmt.Errorf("Error creating Instance: %s", err)
235273
}
236274

237275
// Store the ID now
238-
id, err := replaceVars(d, config, "projects/{{project}}/locations/{{zone}}/instances/{{name}}")
276+
id, err := replaceVars(d, config, "projects/{{project}}/locations/{{location}}/instances/{{name}}")
239277
if err != nil {
240278
return fmt.Errorf("Error constructing id: %s", err)
241279
}
@@ -254,7 +292,7 @@ func resourceFilestoreInstanceCreate(d *schema.ResourceData, meta interface{}) e
254292
}
255293

256294
// This may have caused the ID to update - update it if so.
257-
id, err = replaceVars(d, config, "projects/{{project}}/locations/{{zone}}/instances/{{name}}")
295+
id, err = replaceVars(d, config, "projects/{{project}}/locations/{{location}}/instances/{{name}}")
258296
if err != nil {
259297
return fmt.Errorf("Error constructing id: %s", err)
260298
}
@@ -272,7 +310,7 @@ func resourceFilestoreInstanceRead(d *schema.ResourceData, meta interface{}) err
272310
return err
273311
}
274312

275-
url, err := replaceVars(d, config, "{{FilestoreBasePath}}projects/{{project}}/locations/{{zone}}/instances/{{name}}")
313+
url, err := replaceVars(d, config, "{{FilestoreBasePath}}projects/{{project}}/locations/{{location}}/instances/{{name}}")
276314
if err != nil {
277315
return err
278316
}
@@ -366,7 +404,7 @@ func resourceFilestoreInstanceUpdate(d *schema.ResourceData, meta interface{}) e
366404
mutexKV.Lock(lockName)
367405
defer mutexKV.Unlock(lockName)
368406

369-
url, err := replaceVars(d, config, "{{FilestoreBasePath}}projects/{{project}}/locations/{{zone}}/instances/{{name}}")
407+
url, err := replaceVars(d, config, "{{FilestoreBasePath}}projects/{{project}}/locations/{{location}}/instances/{{name}}")
370408
if err != nil {
371409
return err
372410
}
@@ -438,7 +476,7 @@ func resourceFilestoreInstanceDelete(d *schema.ResourceData, meta interface{}) e
438476
mutexKV.Lock(lockName)
439477
defer mutexKV.Unlock(lockName)
440478

441-
url, err := replaceVars(d, config, "{{FilestoreBasePath}}projects/{{project}}/locations/{{zone}}/instances/{{name}}")
479+
url, err := replaceVars(d, config, "{{FilestoreBasePath}}projects/{{project}}/locations/{{location}}/instances/{{name}}")
442480
if err != nil {
443481
return err
444482
}
@@ -471,16 +509,15 @@ func resourceFilestoreInstanceDelete(d *schema.ResourceData, meta interface{}) e
471509
func resourceFilestoreInstanceImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
472510
config := meta.(*Config)
473511
if err := parseImportId([]string{
474-
"projects/(?P<project>[^/]+)/locations/(?P<zone>[^/]+)/instances/(?P<name>[^/]+)",
475-
"(?P<project>[^/]+)/(?P<zone>[^/]+)/(?P<name>[^/]+)",
476-
"(?P<zone>[^/]+)/(?P<name>[^/]+)",
477-
"(?P<name>[^/]+)",
512+
"projects/(?P<project>[^/]+)/locations/(?P<location>[^/]+)/instances/(?P<name>[^/]+)",
513+
"(?P<project>[^/]+)/(?P<location>[^/]+)/(?P<name>[^/]+)",
514+
"(?P<location>[^/]+)/(?P<name>[^/]+)",
478515
}, d, config); err != nil {
479516
return nil, err
480517
}
481518

482519
// Replace import id for the resource id
483-
id, err := replaceVars(d, config, "projects/{{project}}/locations/{{zone}}/instances/{{name}}")
520+
id, err := replaceVars(d, config, "projects/{{project}}/locations/{{location}}/instances/{{name}}")
484521
if err != nil {
485522
return nil, fmt.Errorf("Error constructing id: %s", err)
486523
}
@@ -700,3 +737,192 @@ func expandFilestoreInstanceNetworksReservedIpRange(v interface{}, d TerraformRe
700737
func expandFilestoreInstanceNetworksIpAddresses(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
701738
return v, nil
702739
}
740+
741+
func resourceFilestoreInstanceResourceV0() *schema.Resource {
742+
return &schema.Resource{
743+
Schema: map[string]*schema.Schema{
744+
"file_shares": {
745+
Type: schema.TypeList,
746+
Required: true,
747+
Description: `File system shares on the instance. For this version, only a
748+
single file share is supported.`,
749+
MaxItems: 1,
750+
Elem: &schema.Resource{
751+
Schema: map[string]*schema.Schema{
752+
"capacity_gb": {
753+
Type: schema.TypeInt,
754+
Required: true,
755+
Description: `File share capacity in GiB. This must be at least 1024 GiB
756+
for the standard tier, or 2560 GiB for the premium tier.`,
757+
},
758+
"name": {
759+
Type: schema.TypeString,
760+
Required: true,
761+
ForceNew: true,
762+
Description: `The name of the fileshare (16 characters or less)`,
763+
},
764+
"nfs_export_options": {
765+
Type: schema.TypeList,
766+
Optional: true,
767+
Description: `Nfs Export Options. There is a limit of 10 export options per file share.`,
768+
MaxItems: 10,
769+
Elem: &schema.Resource{
770+
Schema: map[string]*schema.Schema{
771+
"access_mode": {
772+
Type: schema.TypeString,
773+
Optional: true,
774+
ValidateFunc: validation.StringInSlice([]string{"READ_ONLY", "READ_WRITE", ""}, false),
775+
Description: `Either READ_ONLY, for allowing only read requests on the exported directory,
776+
or READ_WRITE, for allowing both read and write requests. The default is READ_WRITE. Default value: "READ_WRITE" Possible values: ["READ_ONLY", "READ_WRITE"]`,
777+
Default: "READ_WRITE",
778+
},
779+
"anon_gid": {
780+
Type: schema.TypeInt,
781+
Optional: true,
782+
Description: `An integer representing the anonymous group id with a default value of 65534.
783+
Anon_gid may only be set with squashMode of ROOT_SQUASH. An error will be returned
784+
if this field is specified for other squashMode settings.`,
785+
},
786+
"anon_uid": {
787+
Type: schema.TypeInt,
788+
Optional: true,
789+
Description: `An integer representing the anonymous user id with a default value of 65534.
790+
Anon_uid may only be set with squashMode of ROOT_SQUASH. An error will be returned
791+
if this field is specified for other squashMode settings.`,
792+
},
793+
"ip_ranges": {
794+
Type: schema.TypeList,
795+
Optional: true,
796+
Description: `List of either IPv4 addresses, or ranges in CIDR notation which may mount the file share.
797+
Overlapping IP ranges are not allowed, both within and across NfsExportOptions. An error will be returned.
798+
The limit is 64 IP ranges/addresses for each FileShareConfig among all NfsExportOptions.`,
799+
Elem: &schema.Schema{
800+
Type: schema.TypeString,
801+
},
802+
},
803+
"squash_mode": {
804+
Type: schema.TypeString,
805+
Optional: true,
806+
ValidateFunc: validation.StringInSlice([]string{"NO_ROOT_SQUASH", "ROOT_SQUASH", ""}, false),
807+
Description: `Either NO_ROOT_SQUASH, for allowing root access on the exported directory, or ROOT_SQUASH,
808+
for not allowing root access. The default is NO_ROOT_SQUASH. Default value: "NO_ROOT_SQUASH" Possible values: ["NO_ROOT_SQUASH", "ROOT_SQUASH"]`,
809+
Default: "NO_ROOT_SQUASH",
810+
},
811+
},
812+
},
813+
},
814+
},
815+
},
816+
},
817+
"name": {
818+
Type: schema.TypeString,
819+
Required: true,
820+
Description: `The resource name of the instance.`,
821+
},
822+
"networks": {
823+
Type: schema.TypeList,
824+
Required: true,
825+
ForceNew: true,
826+
Description: `VPC networks to which the instance is connected. For this version,
827+
only a single network is supported.`,
828+
MinItems: 1,
829+
Elem: &schema.Resource{
830+
Schema: map[string]*schema.Schema{
831+
"modes": {
832+
Type: schema.TypeList,
833+
Required: true,
834+
ForceNew: true,
835+
Description: `IP versions for which the instance has
836+
IP addresses assigned. Possible values: ["ADDRESS_MODE_UNSPECIFIED", "MODE_IPV4", "MODE_IPV6"]`,
837+
Elem: &schema.Schema{
838+
Type: schema.TypeString,
839+
ValidateFunc: validation.StringInSlice([]string{"ADDRESS_MODE_UNSPECIFIED", "MODE_IPV4", "MODE_IPV6"}, false),
840+
},
841+
},
842+
"network": {
843+
Type: schema.TypeString,
844+
Required: true,
845+
ForceNew: true,
846+
Description: `The name of the GCE VPC network to which the
847+
instance is connected.`,
848+
},
849+
"connect_mode": {
850+
Type: schema.TypeString,
851+
Optional: true,
852+
ForceNew: true,
853+
ValidateFunc: validation.StringInSlice([]string{"DIRECT_PEERING", "PRIVATE_SERVICE_ACCESS", ""}, false),
854+
Description: `The network connect mode of the Filestore instance.
855+
If not provided, the connect mode defaults to
856+
DIRECT_PEERING. Default value: "DIRECT_PEERING" Possible values: ["DIRECT_PEERING", "PRIVATE_SERVICE_ACCESS"]`,
857+
Default: "DIRECT_PEERING",
858+
},
859+
"reserved_ip_range": {
860+
Type: schema.TypeString,
861+
Computed: true,
862+
Optional: true,
863+
Description: `A /29 CIDR block that identifies the range of IP
864+
addresses reserved for this instance.`,
865+
},
866+
"ip_addresses": {
867+
Type: schema.TypeList,
868+
Computed: true,
869+
Description: `A list of IPv4 or IPv6 addresses.`,
870+
Elem: &schema.Schema{
871+
Type: schema.TypeString,
872+
},
873+
},
874+
},
875+
},
876+
},
877+
"tier": {
878+
Type: schema.TypeString,
879+
Required: true,
880+
ForceNew: true,
881+
ValidateFunc: validation.StringInSlice([]string{"TIER_UNSPECIFIED", "STANDARD", "PREMIUM", "BASIC_HDD", "BASIC_SSD", "HIGH_SCALE_SSD"}, false),
882+
Description: `The service tier of the instance. Possible values: ["TIER_UNSPECIFIED", "STANDARD", "PREMIUM", "BASIC_HDD", "BASIC_SSD", "HIGH_SCALE_SSD"]`,
883+
},
884+
"zone": {
885+
Type: schema.TypeString,
886+
Required: true,
887+
ForceNew: true,
888+
Description: `The name of the Filestore zone of the instance.`,
889+
},
890+
"description": {
891+
Type: schema.TypeString,
892+
Optional: true,
893+
Description: `A description of the instance.`,
894+
},
895+
"labels": {
896+
Type: schema.TypeMap,
897+
Optional: true,
898+
Description: `Resource labels to represent user-provided metadata.`,
899+
Elem: &schema.Schema{Type: schema.TypeString},
900+
},
901+
"create_time": {
902+
Type: schema.TypeString,
903+
Computed: true,
904+
Description: `Creation timestamp in RFC3339 text format.`,
905+
},
906+
"etag": {
907+
Type: schema.TypeString,
908+
Computed: true,
909+
Description: `Server-specified ETag for the instance resource to prevent
910+
simultaneous updates from overwriting each other.`,
911+
},
912+
"project": {
913+
Type: schema.TypeString,
914+
Optional: true,
915+
Computed: true,
916+
ForceNew: true,
917+
},
918+
},
919+
}
920+
}
921+
922+
func resourceFilestoreInstanceUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) {
923+
log.Printf("[DEBUG] Attributes before migration: %#v", rawState)
924+
925+
rawState["location"] = rawState["zone"]
926+
log.Printf("[DEBUG] Attributes after migration: %#v", rawState)
927+
return rawState, nil
928+
}

google/resource_filestore_instance_generated_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func TestAccFilestoreInstance_filestoreInstanceBasicExample(t *testing.T) {
4242
ResourceName: "google_filestore_instance.instance",
4343
ImportState: true,
4444
ImportStateVerify: true,
45-
ImportStateVerifyIgnore: []string{"name", "zone"},
45+
ImportStateVerifyIgnore: []string{"name", "zone", "location"},
4646
},
4747
},
4848
})
@@ -52,7 +52,7 @@ func testAccFilestoreInstance_filestoreInstanceBasicExample(context map[string]i
5252
return Nprintf(`
5353
resource "google_filestore_instance" "instance" {
5454
name = "tf-test-test-instance%{random_suffix}"
55-
zone = "us-central1-b"
55+
location = "us-central1-b"
5656
tier = "PREMIUM"
5757
5858
file_shares {
@@ -80,7 +80,7 @@ func testAccCheckFilestoreInstanceDestroyProducer(t *testing.T) func(s *terrafor
8080

8181
config := googleProviderConfig(t)
8282

83-
url, err := replaceVarsForTest(config, rs, "{{FilestoreBasePath}}projects/{{project}}/locations/{{zone}}/instances/{{name}}")
83+
url, err := replaceVarsForTest(config, rs, "{{FilestoreBasePath}}projects/{{project}}/locations/{{location}}/instances/{{name}}")
8484
if err != nil {
8585
return err
8686
}

0 commit comments

Comments
 (0)