Skip to content

feat(instance): add support filesystem #3149

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/resources/file_filesystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ This resource allows you to define and manage the size, tags, and region of a fi
```terraform
resource scaleway_file_filesystem file {
name = "my-nfs-filesystem"
size = 100000000000 # 100 GB
size_in_gb = 100000000000 # 100 GB
}
```

## Argument Reference

- `name` - (Optional) The name of the filesystem. If not provided, a random name will be generated.
- `size` - (Required) The size of the filesystem in bytes, with a granularity of 100 GB (10¹¹ bytes).
- `size_in_gb` - (Required) The size of the filesystem in bytes, with a granularity of 100 GB (10¹¹ bytes).
- Minimum: 100 GB (100000000000 bytes)
- Maximum: 10 TB (10000000000000 bytes)
- `tags` - (Optional) A list of tags associated with the filesystem.
Expand Down
32 changes: 32 additions & 0 deletions docs/resources/instance_server.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,33 @@ resource "scaleway_instance_server" "web" {
}
```

### With filesystem

```terraform
resource scaleway_block_volume volume {
iops = 15000
size_in_gb = 15
}

resource scaleway_file_filesystem terraform_instance_filesystem {
name = "filesystem-instance-terraform"
size_in_gb = 100000000000
}

resource scaleway_instance_server base {
type = "POP2-HM-2C-16G"
state = "started"
tags = ["terraform-test", "scaleway_instance_server", "state"]
root_volume {
volume_type = "sbs_volume"
volume_id = scaleway_block_volume.volume.id
}
filesystems {
filesystem_id = scaleway_file_filesystem.terraform_instance_filesystem.id
}
}
```

### With a reserved IP

```terraform
Expand Down Expand Up @@ -227,6 +254,9 @@ attached to the server. Updates to this field will trigger a stop/start of the s

~> **Important:** If this field contains local volumes, you have to first detach them, in one apply, and then delete the volume in another apply.

- `filesystems` - (Optional) List of filesystems attached to the server.
- `filesystem_id` - (Optional) The unique ID of the filesystem attached to the server.

- `enable_ipv6` - (Defaults to `false`) Determines if IPv6 is enabled for the server.
Deprecated: Please use a scaleway_instance_ip with a `routed_ipv6` type.

Expand Down Expand Up @@ -288,6 +318,8 @@ In addition to all arguments above, the following attributes are exported:
- `placement_group_policy_respected` - (Deprecated) Always false, use [instance_placement_group ressource](instance_placement_group.md) to known when the placement group policy is respected.
- `root_volume`
- `volume_id` - The volume ID of the root volume of the server.
- `filesystem`
- `state` - The current status of the filesystem (e.g., attached, detached).
- `private_ip` - The Scaleway internal IP address of the server (Deprecated use [ipam_ip datasource](../data-sources/ipam_ip.md#instance-private-network-ip) instead).
- `public_ip` - The public IP address of the server (Deprecated use `public_ips` instead).
- `public_ips` - The list of public IPs of the server.
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ require (
github.com/nats-io/jwt/v2 v2.7.4
github.com/nats-io/nats.go v1.38.0
github.com/robfig/cron/v3 v3.0.1
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.33.0.20250604134054-a06406d42247
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.33.0.20250613151004-c065a4eb7430
github.com/stretchr/testify v1.10.0
golang.org/x/crypto v0.38.0
gopkg.in/dnaeon/go-vcr.v3 v3.2.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -447,8 +447,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.33.0.20250604134054-a06406d42247 h1:wlIvcSpGl3mGDpQmwrZHnYMIlB7Mwx3bhg151LG22Ws=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.33.0.20250604134054-a06406d42247/go.mod h1:qiGzapFyNPFwBBLJ+hTFykKSnU95n1zL64+o1ubmwf0=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.33.0.20250613151004-c065a4eb7430 h1:npqerdt+HbDkv1+43FdhXNKnzKqkxfwgCCZDHgZRKNE=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.33.0.20250613151004-c065a4eb7430/go.mod h1:zFWiHphneiey3s8HOtAEnGrRlWivNaxW5T6d5Xfco7g=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
Expand Down
25 changes: 17 additions & 8 deletions internal/services/file/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package file

import (
"context"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"time"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
Expand Down Expand Up @@ -37,10 +38,11 @@ func ResourceFileSystem() *schema.Resource {
Optional: true,
Description: "The name of the filesystem",
},
"size": {
Type: schema.TypeInt,
Required: true,
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.",
"size_in_gb": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntBetween(1, 1000),
Description: "The Filesystem size_in_gb 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_in_gb.",
},
"tags": {
Type: schema.TypeList,
Expand Down Expand Up @@ -87,10 +89,16 @@ func ResourceFileSystemCreate(ctx context.Context, d *schema.ResourceData, m any
Region: region,
Name: types.ExpandOrGenerateString(d.Get("name").(string), "file"),
ProjectID: d.Get("project_id").(string),
Size: *types.ExpandUint64Ptr(d.Get("size")),
Size: *types.ExpandUint64Ptr(d.Get("size_in_gb")),
Tags: types.ExpandStrings(d.Get("tags")),
}

if size, ok := d.GetOk("size_in_gb"); ok {
sizeInGB := size.(int)
sizeInBytes := uint64(sizeInGB) * uint64(scw.GB)
req.Size = sizeInBytes
}

file, err := api.CreateFileSystem(req, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
Expand Down Expand Up @@ -128,7 +136,7 @@ func ResourceFileSystemRead(ctx context.Context, d *schema.ResourceData, m any)
_ = d.Set("region", fileSystem.Region)
_ = d.Set("organization_id", fileSystem.OrganizationID)
_ = d.Set("status", fileSystem.Status)
_ = d.Set("size", int64(fileSystem.Size))
_ = d.Set("size_in_gb", int(fileSystem.Size/scw.GB))
_ = d.Set("tags", fileSystem.Tags)
_ = d.Set("created_at", fileSystem.CreatedAt.Format(time.RFC3339))
_ = d.Set("updated_at", fileSystem.UpdatedAt.Format(time.RFC3339))
Expand Down Expand Up @@ -163,8 +171,9 @@ func ResourceFileSystemUpdate(ctx context.Context, d *schema.ResourceData, m any
req.Name = types.ExpandUpdatedStringPtr(d.Get("name"))
}

if d.HasChange("size") {
req.Size = types.ExpandUint64Ptr(d.Get("size"))
if d.HasChange("size_in_gb") {
sizeInGB := uint64(d.Get("size_in_gb").(int)) * uint64(scw.GB)
req.Size = types.ExpandUint64Ptr(sizeInGB)
}

if d.HasChange("tags") {
Expand Down
28 changes: 14 additions & 14 deletions internal/services/file/filesystem_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func TestAccFileSystem_Basic(t *testing.T) {

fileSystemName := "TestAccFileSystem_Basic"
fileSystemNameUpdated := "TestAccFileSystem_BasicUpdate"
size := int64(100_000_000_000)
sizeInGB := 100

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
Expand All @@ -31,25 +31,25 @@ func TestAccFileSystem_Basic(t *testing.T) {
Config: fmt.Sprintf(`
resource "scaleway_file_filesystem" "fs" {
name = "%s"
size = %d
size_in_gb = %d
}
`, fileSystemName, size),
`, fileSystemName, sizeInGB),
Check: resource.ComposeTestCheckFunc(
testAccCheckFileSystemExists(tt, "scaleway_file_filesystem.fs"),
resource.TestCheckResourceAttr("scaleway_file_filesystem.fs", "name", fileSystemName),
resource.TestCheckResourceAttr("scaleway_file_filesystem.fs", "size", strconv.FormatInt(size, 10)),
resource.TestCheckResourceAttr("scaleway_file_filesystem.fs", "size_in_gb", strconv.Itoa(sizeInGB)),
),
},
{
Config: fmt.Sprintf(`
resource "scaleway_file_filesystem" "fs" {
name = "%s"
size = %d
size_in_gb = %d
}
`, fileSystemNameUpdated, size),
`, fileSystemNameUpdated, sizeInGB),
Check: resource.ComposeTestCheckFunc(
testAccCheckFileSystemExists(tt, "scaleway_file_filesystem.fs"),
resource.TestCheckResourceAttr("scaleway_file_filesystem.fs", "size", strconv.FormatInt(size, 10)),
resource.TestCheckResourceAttr("scaleway_file_filesystem.fs", "size_in_gb", strconv.Itoa(sizeInGB)),
),
},
},
Expand All @@ -61,7 +61,7 @@ func TestAccFileSystem_SizeTooSmallFails(t *testing.T) {
defer tt.Cleanup()

fileSystemName := "TestAccFileSystem_SizeTooSmallFails"
size := int64(10_000_000_000)
sizeInGB := 10

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
Expand All @@ -72,9 +72,9 @@ func TestAccFileSystem_SizeTooSmallFails(t *testing.T) {
Config: fmt.Sprintf(`
resource "scaleway_file_filesystem" "fs" {
name = "%s"
size = %d
size_in_gb = %d
}
`, fileSystemName, size),
`, fileSystemName, sizeInGB),
ExpectError: regexp.MustCompile("size must be greater or equal to 100000000000"),
},
},
Expand All @@ -86,7 +86,7 @@ func TestAccFileSystem_InvalidSizeGranularityFails(t *testing.T) {
defer tt.Cleanup()

fileSystemName := "TestAccFileSystem_InvalidSizeGranularityFails"
size := int64(25_000_000_000)
sizeInGB := 250

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
Expand All @@ -97,10 +97,10 @@ func TestAccFileSystem_InvalidSizeGranularityFails(t *testing.T) {
Config: fmt.Sprintf(`
resource "scaleway_file_filesystem" "fs" {
name = "%s"
size = %d
size_in_gb = %d
}
`, fileSystemName, size),
ExpectError: regexp.MustCompile("size must be greater or equal to 100000000000"),
`, fileSystemName, sizeInGB),
ExpectError: regexp.MustCompile("size does not respect constraint, size must be a multiple of 100000000000"),
},
},
})
Expand Down
Loading
Loading