Skip to content

Commit 7315d2c

Browse files
committed
update doc and tests
1 parent e75cf03 commit 7315d2c

File tree

5 files changed

+182
-55
lines changed

5 files changed

+182
-55
lines changed

docs/resources/instance_server.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,36 @@ resource "scaleway_instance_server" "web" {
4545
}
4646
```
4747

48+
### With filesystem
49+
50+
```terraform
51+
52+
resource "scaleway_block_volume" "volume" {
53+
iops = 15000
54+
size_in_gb = 15
55+
}
56+
57+
resource "scaleway_file_filesystem" "terraform_instance_filesystem"{
58+
name="filesystem-instance-terraform"
59+
size = 100000000000
60+
}
61+
62+
resource "scaleway_instance_server" "base" {
63+
type = "POP2-HM-2C-16G"
64+
state = "started"
65+
tags = [ "terraform-test", "scaleway_instance_server", "state" ]
66+
root_volume {
67+
volume_type = "sbs_volume"
68+
volume_id = scaleway_block_volume.volume.id
69+
}
70+
filesystems {
71+
filesystem_id = scaleway_file_filesystem.terraform_instance_filesystem.id
72+
}
73+
}`
74+
```
75+
76+
77+
4878
### With a reserved IP
4979

5080
```terraform
@@ -227,6 +257,9 @@ attached to the server. Updates to this field will trigger a stop/start of the s
227257

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

260+
- `filesystem` - (Optional) List of filesystems attached to the server.
261+
- `filesystem_id` - (Optional) The unique ID of the filesystem attached to the server.
262+
230263
- `enable_ipv6` - (Defaults to `false`) Determines if IPv6 is enabled for the server.
231264
Deprecated: Please use a scaleway_instance_ip with a `routed_ipv6` type.
232265

@@ -288,6 +321,7 @@ In addition to all arguments above, the following attributes are exported:
288321
- `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.
289322
- `root_volume`
290323
- `volume_id` - The volume ID of the root volume of the server.
324+
- `filesystem` - (Computed) The current status of the filesystem (e.g., attached, detached).
291325
- `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).
292326
- `public_ip` - The public IP address of the server (Deprecated use `public_ips` instead).
293327
- `public_ips` - The list of public IPs of the server.

internal/services/instance/helpers_instance.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,15 @@ const (
3333
// InstanceServerStateStandby transient state of the instance event waiting third action or rescue mode
3434
InstanceServerStateStandby = "standby"
3535

36-
DefaultInstanceServerWaitTimeout = 10 * time.Minute
36+
DefaultInstanceServerWaitTimeout = 15 * time.Minute
3737
defaultInstancePrivateNICWaitTimeout = 10 * time.Minute
3838
defaultInstanceVolumeDeleteTimeout = 10 * time.Minute
3939
defaultInstanceSecurityGroupTimeout = 1 * time.Minute
4040
defaultInstanceSecurityGroupRuleTimeout = 1 * time.Minute
4141
defaultInstancePlacementGroupTimeout = 1 * time.Minute
4242
defaultInstanceIPTimeout = 1 * time.Minute
4343
defaultInstanceIPReverseDNSTimeout = 10 * time.Minute
44+
defaultFileSystemWaitTimeout = 15 * time.Minute
4445

4546
defaultInstanceSnapshotWaitTimeout = 1 * time.Hour
4647

internal/services/instance/server.go

Lines changed: 80 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@ import (
55
"context"
66
"errors"
77
"fmt"
8-
"io"
9-
"log"
10-
"strconv"
11-
"strings"
12-
138
"github.com/google/go-cmp/cmp"
149
"github.com/hashicorp/go-cty/cty"
1510
"github.com/hashicorp/terraform-plugin-log/tflog"
@@ -36,6 +31,10 @@ import (
3631
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/vpc"
3732
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
3833
"github.com/scaleway/terraform-provider-scaleway/v2/internal/verify"
34+
"io"
35+
"log"
36+
"strconv"
37+
"strings"
3938
)
4039

4140
func ResourceServer() *schema.Resource {
@@ -200,7 +199,6 @@ func ResourceServer() *schema.Resource {
200199
"filesystem_id": {
201200
Type: schema.TypeString,
202201
Optional: true,
203-
Computed: true,
204202
Description: "The filesystem ID attached to the server",
205203
},
206204
"status": {
@@ -1119,43 +1117,30 @@ func ResourceInstanceServerUpdate(ctx context.Context, d *schema.ResourceData, m
11191117
///
11201118

11211119
if d.HasChange("filesystems") {
1122-
if fs, ok := d.GetOk("filesystems"); ok {
1123-
for i := range fs.([]interface{}) {
1124-
fsKey := fmt.Sprintf("filesystems.%d.filesystem_id", i)
1125-
if d.HasChange(fsKey) {
1126-
old, new := d.GetChange(fsKey)
1127-
if !cmp.Equal(old, new) {
1128-
_, err := waitForServer(ctx, api.API, zone, id, d.Timeout(schema.TimeoutUpdate))
1129-
if err != nil {
1130-
return diag.FromErr(err)
1131-
}
1120+
oldRaw, newRaw := d.GetChange("filesystems")
11321121

1133-
if old != nil {
1134-
oldFileSystemID := types.ExpandStringPtr(old)
1135-
_, err = api.DetachServerFileSystem(&instanceSDK.DetachServerFileSystemRequest{
1136-
Zone: zone,
1137-
ServerID: server.ID,
1138-
FilesystemID: locality.ExpandID(*oldFileSystemID),
1139-
})
1140-
if err != nil {
1141-
return diag.FromErr(err)
1142-
}
1143-
}
1122+
oldList := oldRaw.([]interface{})
1123+
newList := newRaw.([]interface{})
11441124

1145-
if new != nil {
1146-
newFileSystemID := types.ExpandStringPtr(new)
1147-
_, err = api.AttachServerFileSystem(&instanceSDK.AttachServerFileSystemRequest{
1148-
Zone: zone,
1149-
ServerID: server.ID,
1150-
FilesystemID: locality.ExpandID(*newFileSystemID),
1151-
})
1152-
if err != nil {
1153-
return diag.FromErr(err)
1154-
}
1155-
}
1156-
}
1157-
}
1158-
}
1125+
oldIDs := make(map[string]struct{})
1126+
newIDs := make(map[string]struct{})
1127+
1128+
collectFilesystemIDs(oldList, oldIDs)
1129+
collectFilesystemIDs(newList, newIDs)
1130+
1131+
diagnostics, done := detachOlDFileSystem(oldIDs, newIDs, api, zone, server)
1132+
if done {
1133+
return diagnostics
1134+
}
1135+
1136+
_, err := waitForFilesystems(ctx, api.API, zone, id, *scw.TimeDurationPtr(defaultFileSystemWaitTimeout))
1137+
if err != nil {
1138+
return diag.FromErr(err)
1139+
}
1140+
1141+
d2, done2 := attachNewFileSystem(newIDs, oldIDs, api, zone, server)
1142+
if done2 {
1143+
return d2
11591144
}
11601145
}
11611146

@@ -1253,6 +1238,46 @@ func ResourceInstanceServerUpdate(ctx context.Context, d *schema.ResourceData, m
12531238
return append(warnings, ResourceInstanceServerRead(ctx, d, m)...)
12541239
}
12551240

1241+
func attachNewFileSystem(newIDs map[string]struct{}, oldIDs map[string]struct{}, api *instancehelpers.BlockAndInstanceAPI, zone scw.Zone, server *instanceSDK.Server) (diag.Diagnostics, bool) {
1242+
for id := range newIDs {
1243+
if _, alreadyAttached := oldIDs[id]; !alreadyAttached {
1244+
_, err := api.AttachServerFileSystem(&instanceSDK.AttachServerFileSystemRequest{
1245+
Zone: zone,
1246+
ServerID: server.ID,
1247+
FilesystemID: locality.ExpandID(id),
1248+
})
1249+
if err != nil {
1250+
return diag.FromErr(fmt.Errorf("error attaching filesystem %s: %w", id, err)), true
1251+
}
1252+
}
1253+
}
1254+
return nil, false
1255+
}
1256+
1257+
func detachOlDFileSystem(oldIDs map[string]struct{}, newIDs map[string]struct{}, api *instancehelpers.BlockAndInstanceAPI, zone scw.Zone, server *instanceSDK.Server) (diag.Diagnostics, bool) {
1258+
for id := range oldIDs {
1259+
if _, stillPresent := newIDs[id]; !stillPresent {
1260+
_, err := api.DetachServerFileSystem(&instanceSDK.DetachServerFileSystemRequest{
1261+
Zone: zone,
1262+
ServerID: server.ID,
1263+
FilesystemID: locality.ExpandID(id),
1264+
})
1265+
if err != nil {
1266+
return diag.FromErr(fmt.Errorf("error detaching filesystem %s: %w", id, err)), true
1267+
}
1268+
}
1269+
}
1270+
return nil, false
1271+
}
1272+
1273+
func collectFilesystemIDs(fsList []interface{}, target map[string]struct{}) {
1274+
for _, fs := range fsList {
1275+
if fsMap, ok := fs.(map[string]interface{}); ok {
1276+
id := fsMap["filesystem_id"].(string)
1277+
target[id] = struct{}{}
1278+
}
1279+
}
1280+
}
12561281
func ResourceInstanceServerDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
12571282
api, zone, id, err := instancehelpers.InstanceAndBlockAPIWithZoneAndID(m, d.Id())
12581283
if err != nil {
@@ -1292,11 +1317,20 @@ func ResourceInstanceServerDelete(ctx context.Context, d *schema.ResourceData, m
12921317

12931318
// Detach filesystem
12941319
if filesystems, ok := d.GetOk("filesystems"); ok {
1295-
for index := range filesystems.([]interface{}) {
1296-
filesystemKey := fmt.Sprintf("filesystem.%d.filesystem_id", index)
1297-
fs := d.Get(filesystemKey)
1298-
newFileSystemID := types.ExpandStringPtr(fs)
1299-
_, err = api.AttachServerFileSystem(&instanceSDK.AttachServerFileSystemRequest{
1320+
fsList := filesystems.([]interface{})
1321+
for i, fsRaw := range fsList {
1322+
fsMap := fsRaw.(map[string]interface{})
1323+
fsIDRaw, ok := fsMap["filesystem_id"]
1324+
if !ok || fsIDRaw == nil {
1325+
return diag.Errorf("filesystem_id is missing or nil for filesystem at index %d", i)
1326+
}
1327+
fsID := fsIDRaw.(string)
1328+
newFileSystemID := types.ExpandStringPtr(fsID)
1329+
if newFileSystemID == nil {
1330+
return diag.Errorf("failed to expand filesystem_id pointer at index %d", i)
1331+
}
1332+
1333+
_, err = api.DetachServerFileSystem(&instanceSDK.DetachServerFileSystemRequest{
13001334
Zone: zone,
13011335
ServerID: id,
13021336
FilesystemID: locality.ExpandID(*newFileSystemID),

internal/services/instance/server_test.go

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2116,7 +2116,7 @@ func TestAccServer_AttachDetachFileSystem(t *testing.T) {
21162116
}
21172117
21182118
resource "scaleway_instance_server" "base" {
2119-
type = "POP2-2C-8G"
2119+
type = "POP2-HM-2C-16G"
21202120
state = "started"
21212121
tags = [ "terraform-test", "scaleway_instance_server", "state" ]
21222122
root_volume {
@@ -2129,7 +2129,7 @@ func TestAccServer_AttachDetachFileSystem(t *testing.T) {
21292129
}`,
21302130
Check: resource.ComposeTestCheckFunc(
21312131
isServerPresent(tt, "scaleway_instance_server.base"),
2132-
resource.TestCheckResourceAttr("scaleway_instance_server.base", "type", "POP2-2C-8G"),
2132+
resource.TestCheckResourceAttr("scaleway_instance_server.base", "type", "POP2-HM-2C-16G"),
21332133
resource.TestCheckResourceAttr("scaleway_instance_server.base", "root_volume.0.delete_on_termination", "true"),
21342134
resource.TestCheckResourceAttr("scaleway_instance_server.base", "root_volume.0.size_in_gb", "15"),
21352135
resource.TestCheckResourceAttrSet("scaleway_instance_server.base", "root_volume.0.volume_id"),
@@ -2158,29 +2158,72 @@ func TestAccServer_AttachDetachFileSystem(t *testing.T) {
21582158
}
21592159
21602160
resource "scaleway_instance_server" "base" {
2161-
type = "POP2-2C-8G"
2161+
type = "POP2-HM-2C-16G"
21622162
state = "started"
21632163
tags = [ "terraform-test", "scaleway_instance_server", "state" ]
21642164
root_volume {
21652165
volume_type = "sbs_volume"
21662166
volume_id = scaleway_block_volume.volume.id
21672167
}
2168-
filesystems {
2169-
filesystem_id = scaleway_file_filesystem.terraform_instance_filesystem.id
2170-
}
21712168
21722169
filesystems {
21732170
filesystem_id = scaleway_file_filesystem.terraform_instance_filesystem_2.id
21742171
}
21752172
}`,
21762173
Check: resource.ComposeTestCheckFunc(
21772174
isServerPresent(tt, "scaleway_instance_server.base"),
2178-
resource.TestCheckResourceAttr("scaleway_instance_server.base", "type", "POP2-2C-8G"),
2175+
resource.TestCheckResourceAttr("scaleway_instance_server.base", "type", "POP2-HM-2C-16G"),
2176+
resource.TestCheckResourceAttr("scaleway_instance_server.base", "root_volume.0.delete_on_termination", "true"),
2177+
resource.TestCheckResourceAttr("scaleway_instance_server.base", "root_volume.0.size_in_gb", "15"),
2178+
resource.TestCheckResourceAttrSet("scaleway_instance_server.base", "root_volume.0.volume_id"),
2179+
resource.TestCheckResourceAttrSet("scaleway_instance_server.base", "filesystems.0.filesystem_id"),
2180+
resource.TestCheckNoResourceAttr("scaleway_instance_server.base", "filesystems.1.filesystem_id"),
2181+
serverHasNewVolume(tt, "scaleway_instance_server.base"),
2182+
resource.TestCheckResourceAttr("scaleway_instance_server.base", "tags.0", "terraform-test"),
2183+
resource.TestCheckResourceAttr("scaleway_instance_server.base", "tags.1", "scaleway_instance_server"),
2184+
resource.TestCheckResourceAttr("scaleway_instance_server.base", "tags.2", "state"),
2185+
),
2186+
},
2187+
{
2188+
Config: `
2189+
resource "scaleway_block_volume" "volume" {
2190+
iops = 15000
2191+
size_in_gb = 15
2192+
}
2193+
2194+
resource "scaleway_file_filesystem" "terraform_instance_filesystem"{
2195+
name="filesystem-instance-terraform-test"
2196+
size = 100000000000
2197+
}
2198+
2199+
resource "scaleway_file_filesystem" "terraform_instance_filesystem_2"{
2200+
name="filesystem-instance-terraform-test-2"
2201+
size = 100000000000
2202+
}
2203+
2204+
resource "scaleway_instance_server" "base" {
2205+
type = "POP2-HM-2C-16G"
2206+
state = "started"
2207+
tags = [ "terraform-test", "scaleway_instance_server", "state" ]
2208+
root_volume {
2209+
volume_type = "sbs_volume"
2210+
volume_id = scaleway_block_volume.volume.id
2211+
}
2212+
filesystems {
2213+
filesystem_id = scaleway_file_filesystem.terraform_instance_filesystem_2.id
2214+
}
2215+
filesystems {
2216+
filesystem_id = scaleway_file_filesystem.terraform_instance_filesystem.id
2217+
}
2218+
}`,
2219+
Check: resource.ComposeTestCheckFunc(
2220+
isServerPresent(tt, "scaleway_instance_server.base"),
2221+
resource.TestCheckResourceAttr("scaleway_instance_server.base", "type", "POP2-HM-2C-16G"),
21792222
resource.TestCheckResourceAttr("scaleway_instance_server.base", "root_volume.0.delete_on_termination", "true"),
21802223
resource.TestCheckResourceAttr("scaleway_instance_server.base", "root_volume.0.size_in_gb", "15"),
21812224
resource.TestCheckResourceAttrSet("scaleway_instance_server.base", "root_volume.0.volume_id"),
21822225
resource.TestCheckResourceAttrSet("scaleway_instance_server.base", "filesystems.0.filesystem_id"),
2183-
resource.TestCheckResourceAttrSet("scaleway_instance_server.base", "filesystems.0.filesystem_id_2"),
2226+
resource.TestCheckResourceAttrSet("scaleway_instance_server.base", "filesystems.1.filesystem_id"),
21842227
serverHasNewVolume(tt, "scaleway_instance_server.base"),
21852228
resource.TestCheckResourceAttr("scaleway_instance_server.base", "tags.0", "terraform-test"),
21862229
resource.TestCheckResourceAttr("scaleway_instance_server.base", "tags.1", "scaleway_instance_server"),

internal/services/instance/waiters.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,18 @@ func waitForImage(ctx context.Context, api *instance.API, zone scw.Zone, id stri
9191

9292
return image, err
9393
}
94+
95+
func waitForFilesystems(ctx context.Context, api *instance.API, zone scw.Zone, id string, timeout time.Duration) (*instance.Server, error) {
96+
retryInterval := instancehelpers.DefaultInstanceRetryInterval
97+
if transport.DefaultWaitRetryInterval != nil {
98+
retryInterval = *transport.DefaultWaitRetryInterval
99+
}
100+
server, err := api.WaitForServerFileSystem(&instance.WaitForServerFileSystemRequest{
101+
ServerID: id,
102+
Zone: zone,
103+
Timeout: scw.TimeDurationPtr(timeout),
104+
RetryInterval: &retryInterval,
105+
}, scw.WithContext(ctx))
106+
107+
return server, err
108+
}

0 commit comments

Comments
 (0)