Skip to content

Commit 75f2024

Browse files
Laure-diremyleone
andauthored
feat(file): add support v1beta1 (#3141)
* feat(file): add support v1beta1 * Create, Read and Update function * Delete Methode * add tests * fix date issue and register cassettes * doc: create and update documentation * doc: create and update documentation * chore: tidy Go modules and update go.sum * test: fix filesystem size assertion by using strconv.FormatInt * doc: error checking file contents fix * test: add validation for filesystem size granularity * fix: convertion * chore: add file to github action * test: add testing files to exceptionsCassettesCases * test: add testing files to exceptionsCassettesCases * Update docs/resources/file_filesystem.md Co-authored-by: Rémy Léone <[email protected]> --------- Co-authored-by: Rémy Léone <[email protected]>
1 parent 7119759 commit 75f2024

15 files changed

+1421
-13
lines changed

.github/labeler.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,8 @@ webhosting:
117117
- changed-files:
118118
- any-glob-to-any-file:
119119
- internal/services/webhosting/**
120+
file:
121+
- changed-files:
122+
- any-glob-to-any-file:
123+
- internal/services/file/**
124+

.github/workflows/acceptance-tests.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919
- cockpit
2020
- container
2121
- domain
22+
- file
2223
- flexibleip
2324
- function
2425
- iam

docs/resources/file_filesystem.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
subcategory: "File"
3+
page_title: "Scaleway: scaleway_file_filesystem"
4+
---
5+
6+
# Resource: scaleway_file_filesystem
7+
8+
Creates and manages a Scaleway File Storage (NFS) filesystem in a specific region. A filesystem is a scalable storage resource that can be mounted on Compute instances and is typically used for shared, persistent storage.
9+
10+
This resource allows you to define and manage the size, tags, and region of a filesystem, and track its creation and update timestamps, current status, and number of active attachments.
11+
12+
## Example Usage
13+
14+
### Basic
15+
16+
```terraform
17+
resource scaleway_file_filesystem file {
18+
name = "my-nfs-filesystem"
19+
size = 100000000000 # 100 GB
20+
}
21+
```
22+
23+
## Argument Reference
24+
25+
- `name` - (Optional) The name of the filesystem. If not provided, a random name will be generated.
26+
- `size` - (Required) The size of the filesystem in bytes, with a granularity of 100 GB (10¹¹ bytes).
27+
- Minimum: 100 GB (100000000000 bytes)
28+
- Maximum: 10 TB (10000000000000 bytes)
29+
- `tags` - (Optional) A list of tags associated with the filesystem.
30+
- `region` - (Defaults to [provider](../index.md#region) `region`) The region where the filesystem will be created (e.g., fr-par, nl-ams).
31+
- `project_id` - (Defaults to [provider](../index.md#project_id) `project_id`) The ID of the project the server is
32+
associated with.
33+
- `organization_id` - (Defaults to [provider](../index.md#organization_id) `organization_id`) The ID of the organization the user is associated with.
34+
35+
## Attributes Reference
36+
37+
In addition to all arguments above, the following attributes are exported:
38+
39+
- `id` - The ID of the filesystem.
40+
- `status` - The current status of the filesystem. Possible values include creating, available, etc.
41+
- `number_of_attachments` - The number of active attachments (mounts) on the filesystem.
42+
- `created_at` - The date and time when the File Storage filesystem was created.
43+
- `updated_at` - The date and time of the last update to the File Storage filesystem.
44+
45+
## Import
46+
47+
48+
File Storage filesystems can be imported using the `{region}/{id}`, e.g.
49+
50+
```bash
51+
terraform import scaleway_file_filesystem.main fr-par/11111111-1111-1111-1111-111111111111
52+
```

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ require (
2828
github.com/nats-io/jwt/v2 v2.7.4
2929
github.com/nats-io/nats.go v1.38.0
3030
github.com/robfig/cron/v3 v3.0.1
31-
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.33.0.20250512145715-0fc65cc3636b
31+
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.33.0.20250604134054-a06406d42247
3232
github.com/stretchr/testify v1.10.0
3333
golang.org/x/crypto v0.38.0
3434
gopkg.in/dnaeon/go-vcr.v3 v3.2.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,8 +447,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
447447
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
448448
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
449449
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
450-
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.33.0.20250512145715-0fc65cc3636b h1:wzu3hPSNK2PPo7OXBzofeS5hOWqnVRP8xqIXom9ufoc=
451-
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.33.0.20250512145715-0fc65cc3636b/go.mod h1:qiGzapFyNPFwBBLJ+hTFykKSnU95n1zL64+o1ubmwf0=
450+
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.33.0.20250604134054-a06406d42247 h1:wlIvcSpGl3mGDpQmwrZHnYMIlB7Mwx3bhg151LG22Ws=
451+
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.33.0.20250604134054-a06406d42247/go.mod h1:qiGzapFyNPFwBBLJ+hTFykKSnU95n1zL64+o1ubmwf0=
452452
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
453453
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
454454
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=

internal/acctest/validate_cassettes_test.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@ import (
1717

1818
func exceptionsCassettesCases() map[string]struct{} {
1919
return map[string]struct{}{
20-
"../services/mnq/testdata/sns-topic-basic.cassette.yaml": {},
21-
"../services/mnq/testdata/sns-topic-subscription-basic.cassette.yaml": {},
22-
"../services/mnq/testdata/sqs-already-activated.cassette.yaml": {},
23-
"../services/object/testdata/bucket-cors-empty-origin.cassette.yaml": {},
24-
"../services/object/testdata/bucket-destroy-force.cassette.yaml": {},
25-
"../services/rdb/testdata/data-source-privilege-basic.cassette.yaml": {},
26-
"../services/rdb/testdata/privilege-basic.cassette.yaml": {},
27-
"../services/object/testdata/object-bucket-destroy-force.cassette.yaml": {},
28-
"../services/secret/testdata/secret-protected.cassette.yaml": {},
29-
"../services/secret/testdata/secret-version-type.cassette.yaml": {},
20+
"../services/mnq/testdata/sns-topic-basic.cassette.yaml": {},
21+
"../services/mnq/testdata/sns-topic-subscription-basic.cassette.yaml": {},
22+
"../services/mnq/testdata/sqs-already-activated.cassette.yaml": {},
23+
"../services/object/testdata/bucket-cors-empty-origin.cassette.yaml": {},
24+
"../services/object/testdata/bucket-destroy-force.cassette.yaml": {},
25+
"../services/rdb/testdata/data-source-privilege-basic.cassette.yaml": {},
26+
"../services/rdb/testdata/privilege-basic.cassette.yaml": {},
27+
"../services/object/testdata/object-bucket-destroy-force.cassette.yaml": {},
28+
"../services/secret/testdata/secret-protected.cassette.yaml": {},
29+
"../services/secret/testdata/secret-version-type.cassette.yaml": {},
30+
"../services/file/testdata/file-system-invalid-size-granularity-fails.cassette.yaml": {},
31+
"../services/file/testdata/file-system-size-too-small-fails.cassette.yaml": {},
3032
}
3133
}
3234

internal/provider/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/container"
2222
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/domain"
2323
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/edgeservices"
24+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/file"
2425
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/flexibleip"
2526
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/function"
2627
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/iam"
@@ -151,6 +152,7 @@ func Provider(config *Config) plugin.ProviderFunc {
151152
"scaleway_edge_services_route_stage": edgeservices.ResourceRouteStage(),
152153
"scaleway_edge_services_tls_stage": edgeservices.ResourceTLSStage(),
153154
"scaleway_edge_services_waf_stage": edgeservices.ResourceWAFStage(),
155+
"scaleway_file_filesystem": file.ResourceFileSystem(),
154156
"scaleway_flexible_ip": flexibleip.ResourceIP(),
155157
"scaleway_flexible_ip_mac_address": flexibleip.ResourceMACAddress(),
156158
"scaleway_function": function.ResourceFunction(),

internal/services/file/filesystem.go

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
package file
2+
3+
import (
4+
"context"
5+
"time"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
file "github.com/scaleway/scaleway-sdk-go/api/file/v1alpha1"
10+
"github.com/scaleway/scaleway-sdk-go/scw"
11+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors"
12+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional"
13+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account"
14+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
15+
)
16+
17+
func ResourceFileSystem() *schema.Resource {
18+
return &schema.Resource{
19+
CreateContext: ResourceFileSystemCreate,
20+
ReadContext: ResourceFileSystemRead,
21+
UpdateContext: ResourceFileSystemUpdate,
22+
DeleteContext: ResourceFileSystemDelete,
23+
Importer: &schema.ResourceImporter{
24+
StateContext: schema.ImportStatePassthroughContext,
25+
},
26+
Timeouts: &schema.ResourceTimeout{
27+
Create: schema.DefaultTimeout(defaultFileSystemTimeout),
28+
Read: schema.DefaultTimeout(defaultFileSystemTimeout),
29+
Delete: schema.DefaultTimeout(defaultFileSystemTimeout),
30+
Default: schema.DefaultTimeout(defaultFileSystemTimeout),
31+
},
32+
SchemaVersion: 0,
33+
Schema: map[string]*schema.Schema{
34+
"name": {
35+
Type: schema.TypeString,
36+
Computed: true,
37+
Optional: true,
38+
Description: "The name of the filesystem",
39+
},
40+
"size": {
41+
Type: schema.TypeInt,
42+
Required: true,
43+
Description: "The Filesystem size in bytes, with a granularity of 100 GB (10^11 bytes). Must be compliant with the minimum (100 GB) and maximum (10 TB) allowed size.",
44+
},
45+
"tags": {
46+
Type: schema.TypeList,
47+
Elem: &schema.Schema{
48+
Type: schema.TypeString,
49+
},
50+
Optional: true,
51+
Description: "The list of tags assigned to the filesystem",
52+
},
53+
"project_id": account.ProjectIDSchema(),
54+
"organization_id": account.OrganizationIDSchema(),
55+
"region": regional.Schema(),
56+
"status": {
57+
Type: schema.TypeString,
58+
Computed: true,
59+
Description: "The Current status of the filesystem (e.g. creating, available, ...)",
60+
},
61+
"number_of_attachments": {
62+
Type: schema.TypeInt,
63+
Computed: true,
64+
Description: "The current number of attachments (mounts) that the filesystem has",
65+
},
66+
"created_at": {
67+
Type: schema.TypeString,
68+
Computed: true,
69+
Description: "The creation date of the filesystem",
70+
},
71+
"updated_at": {
72+
Type: schema.TypeString,
73+
Computed: true,
74+
Description: "The last update date of the properties of the filesystem",
75+
},
76+
},
77+
}
78+
}
79+
80+
func ResourceFileSystemCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
81+
api, region, err := fileSystemAPIWithZone(d, m)
82+
if err != nil {
83+
return diag.FromErr(err)
84+
}
85+
86+
req := &file.CreateFileSystemRequest{
87+
Region: region,
88+
Name: types.ExpandOrGenerateString(d.Get("name").(string), "file"),
89+
ProjectID: d.Get("project_id").(string),
90+
Size: *types.ExpandUint64Ptr(d.Get("size")),
91+
Tags: types.ExpandStrings(d.Get("tags")),
92+
}
93+
94+
file, err := api.CreateFileSystem(req, scw.WithContext(ctx))
95+
if err != nil {
96+
return diag.FromErr(err)
97+
}
98+
99+
d.SetId(regional.NewIDString(region, file.ID))
100+
101+
_, err = waitForFileSystem(ctx, api, region, file.ID, d.Timeout(schema.TimeoutCreate))
102+
if err != nil {
103+
return diag.FromErr(err)
104+
}
105+
106+
return ResourceFileSystemRead(ctx, d, m)
107+
}
108+
109+
func ResourceFileSystemRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
110+
api, region, id, err := NewAPIWithRegionAndID(m, d.Id())
111+
if err != nil {
112+
return diag.FromErr(err)
113+
}
114+
115+
fileSystem, err := waitForFileSystem(ctx, api, region, id, d.Timeout(schema.TimeoutRead))
116+
if err != nil {
117+
if httperrors.Is404(err) {
118+
d.SetId("")
119+
120+
return nil
121+
}
122+
123+
return diag.FromErr(err)
124+
}
125+
126+
_ = d.Set("name", fileSystem.Name)
127+
_ = d.Set("project_id", fileSystem.ProjectID)
128+
_ = d.Set("region", fileSystem.Region)
129+
_ = d.Set("organization_id", fileSystem.OrganizationID)
130+
_ = d.Set("status", fileSystem.Status)
131+
_ = d.Set("size", int64(fileSystem.Size))
132+
_ = d.Set("tags", fileSystem.Tags)
133+
_ = d.Set("created_at", fileSystem.CreatedAt.Format(time.RFC3339))
134+
_ = d.Set("updated_at", fileSystem.UpdatedAt.Format(time.RFC3339))
135+
_ = d.Set("number_of_attachments", int64(fileSystem.NumberOfAttachments))
136+
137+
return nil
138+
}
139+
140+
func ResourceFileSystemUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
141+
api, region, id, err := NewAPIWithRegionAndID(m, d.Id())
142+
if err != nil {
143+
return diag.FromErr(err)
144+
}
145+
146+
fileSystem, err := waitForFileSystem(ctx, api, region, id, d.Timeout(schema.TimeoutUpdate))
147+
if err != nil {
148+
if httperrors.Is404(err) {
149+
d.SetId("")
150+
151+
return nil
152+
}
153+
154+
return diag.FromErr(err)
155+
}
156+
157+
req := &file.UpdateFileSystemRequest{
158+
Region: region,
159+
FilesystemID: fileSystem.ID,
160+
}
161+
162+
if d.HasChange("name") {
163+
req.Name = types.ExpandUpdatedStringPtr(d.Get("name"))
164+
}
165+
166+
if d.HasChange("size") {
167+
req.Size = types.ExpandUint64Ptr(d.Get("size"))
168+
}
169+
170+
if d.HasChange("tags") {
171+
req.Tags = types.ExpandStringsPtr(d.Get("tags"))
172+
}
173+
174+
if _, err := api.UpdateFileSystem(req, scw.WithContext(ctx)); err != nil {
175+
return diag.FromErr(err)
176+
}
177+
178+
return ResourceFileSystemRead(ctx, d, m)
179+
}
180+
181+
func ResourceFileSystemDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
182+
api, region, id, err := NewAPIWithRegionAndID(m, d.Id())
183+
if err != nil {
184+
return diag.FromErr(err)
185+
}
186+
187+
_, err = waitForFileSystem(ctx, api, region, id, d.Timeout(schema.TimeoutDelete))
188+
if err != nil {
189+
if httperrors.Is404(err) {
190+
d.SetId("")
191+
192+
return nil
193+
}
194+
195+
return diag.FromErr(err)
196+
}
197+
198+
err = api.DeleteFileSystem(&file.DeleteFileSystemRequest{
199+
Region: region,
200+
FilesystemID: id,
201+
}, scw.WithContext(ctx))
202+
if err != nil {
203+
return diag.FromErr(err)
204+
}
205+
206+
_, err = waitForFileSystem(ctx, api, region, id, d.Timeout(schema.TimeoutDelete))
207+
if err != nil && !httperrors.Is404(err) {
208+
return diag.FromErr(err)
209+
}
210+
211+
return nil
212+
}

0 commit comments

Comments
 (0)