Skip to content

Commit e712a91

Browse files
authored
feat(instance_image): support block snapshots (#2823)
* feat(instance_image): support block snapshots * fix: do not query snapshots before creating instance_image * record test * go mod tidy * fix test split block volumes creations in two steps. Forcing order also force IDs with cassettes
1 parent ad60c88 commit e712a91

11 files changed

+3302
-74
lines changed

go.mod

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ require (
2323
github.com/nats-io/jwt/v2 v2.7.2
2424
github.com/nats-io/nats.go v1.37.0
2525
github.com/robfig/cron/v3 v3.0.1
26-
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30.0.20241028153617-2a48843b5fcb
27-
github.com/stretchr/testify v1.10.0
28-
golang.org/x/crypto v0.29.0
26+
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30.0.20241129094524-023aa8142bc1
27+
github.com/stretchr/testify v1.9.0
28+
golang.org/x/crypto v0.28.0
2929
gopkg.in/dnaeon/go-vcr.v3 v3.2.0
3030
)
3131

go.sum

+8-8
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,8 @@ github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXq
242242
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
243243
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
244244
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
245-
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30.0.20241028153617-2a48843b5fcb h1:OsRpbw60numCy/+3FS7UhZzkdiTu6OZwq29bb4b3gNo=
246-
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30.0.20241028153617-2a48843b5fcb/go.mod h1:3jrRJM7638J+P33hKy9MBvfOBxNo8pEGNQQoIv65Ihg=
245+
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30.0.20241129094524-023aa8142bc1 h1:0OKzyRfLH+dWSPOBvwbhNcBTbEiuNkv8mdYGev1+/1g=
246+
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30.0.20241129094524-023aa8142bc1/go.mod h1:kAoejOVBg1E/aVAR6IwKWEmbLCEg2IXklzPAkxzAaXA=
247247
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
248248
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
249249
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
@@ -261,8 +261,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
261261
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
262262
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
263263
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
264-
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
265-
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
264+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
265+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
266266
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
267267
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
268268
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
@@ -306,8 +306,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
306306
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
307307
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
308308
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
309-
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
310-
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
309+
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
310+
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
311311
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
312312
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
313313
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -353,8 +353,8 @@ golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
353353
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
354354
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
355355
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
356-
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
357-
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
356+
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
357+
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
358358
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
359359
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
360360
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=

internal/services/block/snapshot.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ func ResourceBlockSnapshotDelete(ctx context.Context, d *schema.ResourceData, m
156156
return diag.FromErr(err)
157157
}
158158

159-
_, err = waitForBlockSnapshot(ctx, api, zone, id, d.Timeout(schema.TimeoutDelete))
159+
_, err = waitForBlockSnapshotToBeAvailable(ctx, api, zone, id, d.Timeout(schema.TimeoutDelete))
160160
if err != nil {
161161
return diag.FromErr(err)
162162
}

internal/services/block/waiters.go

+19
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,22 @@ func waitForBlockSnapshot(ctx context.Context, blockAPI *block.API, zone scw.Zon
4040

4141
return snapshot, err
4242
}
43+
44+
func waitForBlockSnapshotToBeAvailable(ctx context.Context, blockAPI *block.API, zone scw.Zone, id string, timeout time.Duration) (*block.Snapshot, error) {
45+
retryInterval := defaultBlockRetryInterval
46+
if transport.DefaultWaitRetryInterval != nil {
47+
retryInterval = *transport.DefaultWaitRetryInterval
48+
}
49+
50+
terminalStatus := block.SnapshotStatusAvailable
51+
snapshot, err := blockAPI.WaitForSnapshot(&block.WaitForSnapshotRequest{
52+
Zone: zone,
53+
SnapshotID: id,
54+
RetryInterval: &retryInterval,
55+
Timeout: scw.TimeDurationPtr(timeout),
56+
57+
TerminalStatus: &terminalStatus,
58+
}, scw.WithContext(ctx))
59+
60+
return snapshot, err
61+
}

internal/services/instance/helpers_instance.go

+1-20
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ func reachState(ctx context.Context, api *BlockAndInstanceAPI, zone scw.Zone, se
179179
if err != nil {
180180
return err
181181
}
182-
} else if volume.State != instance.VolumeServerStateAvailable {
182+
} else if volume.State != nil && *volume.State != instance.VolumeServerStateAvailable {
183183
_, err = api.WaitForVolume(&instance.WaitForVolumeRequest{
184184
Zone: zone,
185185
VolumeID: volume.ID,
@@ -407,25 +407,6 @@ func (ph *privateNICsHandler) get(key string) (interface{}, error) {
407407
}, nil
408408
}
409409

410-
func getSnapshotsFromIDs(ctx context.Context, snapIDs []interface{}, instanceAPI *instance.API) ([]*instance.GetSnapshotResponse, error) {
411-
snapResponses := []*instance.GetSnapshotResponse(nil)
412-
for _, snapID := range snapIDs {
413-
zone, id, err := zonal.ParseID(snapID.(string))
414-
if err != nil {
415-
return nil, err
416-
}
417-
snapshot, err := instanceAPI.GetSnapshot(&instance.GetSnapshotRequest{
418-
Zone: zone,
419-
SnapshotID: id,
420-
}, scw.WithContext(ctx))
421-
if err != nil {
422-
return snapResponses, fmt.Errorf("extra volumes : could not find snapshot with id %s", snapID)
423-
}
424-
snapResponses = append(snapResponses, snapshot)
425-
}
426-
return snapResponses, nil
427-
}
428-
429410
func formatImageLabel(imageUUID string) string {
430411
return strings.ReplaceAll(imageUUID, "-", "_")
431412
}

internal/services/instance/helpers_instance_block.go

+51
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ func (volume *UnknownVolume) IsAttached() bool {
8383
return volume.ServerID != nil && *volume.ServerID != ""
8484
}
8585

86+
type UnknownSnapshot struct {
87+
Zone scw.Zone
88+
ID string
89+
Name string
90+
VolumeType instance.VolumeVolumeType
91+
}
92+
8693
func (api *BlockAndInstanceAPI) GetUnknownVolume(req *GetUnknownVolumeRequest, opts ...scw.RequestOption) (*UnknownVolume, error) {
8794
getVolumeResponse, err := api.API.GetVolume(&instance.GetVolumeRequest{
8895
Zone: req.Zone,
@@ -161,6 +168,50 @@ func (api *BlockAndInstanceAPI) ResizeUnknownVolume(req *ResizeUnknownVolumeRequ
161168
return err
162169
}
163170

171+
type GetUnknownSnapshotRequest struct {
172+
Zone scw.Zone
173+
SnapshotID string
174+
}
175+
176+
func (api *BlockAndInstanceAPI) GetUnknownSnapshot(req *GetUnknownSnapshotRequest, opts ...scw.RequestOption) (*UnknownSnapshot, error) {
177+
getSnapshotResponse, err := api.GetSnapshot(&instance.GetSnapshotRequest{
178+
Zone: req.Zone,
179+
SnapshotID: req.SnapshotID,
180+
}, opts...)
181+
notFoundErr := &scw.ResourceNotFoundError{}
182+
if err != nil && !errors.As(err, &notFoundErr) {
183+
return nil, err
184+
}
185+
186+
if getSnapshotResponse != nil {
187+
snap := &UnknownSnapshot{
188+
Zone: getSnapshotResponse.Snapshot.Zone,
189+
ID: getSnapshotResponse.Snapshot.ID,
190+
Name: getSnapshotResponse.Snapshot.Name,
191+
VolumeType: getSnapshotResponse.Snapshot.VolumeType,
192+
}
193+
194+
return snap, nil
195+
}
196+
197+
blockSnapshot, err := api.blockAPI.GetSnapshot(&block.GetSnapshotRequest{
198+
Zone: req.Zone,
199+
SnapshotID: req.SnapshotID,
200+
}, opts...)
201+
if err != nil {
202+
return nil, err
203+
}
204+
205+
snap := &UnknownSnapshot{
206+
Zone: blockSnapshot.Zone,
207+
ID: blockSnapshot.ID,
208+
Name: blockSnapshot.Name,
209+
VolumeType: instance.VolumeVolumeTypeSbsSnapshot,
210+
}
211+
212+
return snap, nil
213+
}
214+
164215
// newAPIWithZone returns a new instance API and the zone for a Create request
165216
func instanceAndBlockAPIWithZone(d *schema.ResourceData, m interface{}) (*BlockAndInstanceAPI, scw.Zone, error) {
166217
instanceAPI := instance.NewAPI(meta.ExtractScwClient(m))

internal/services/instance/image.go

+11-18
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/scaleway/scaleway-sdk-go/scw"
1111
"github.com/scaleway/terraform-provider-scaleway/v2/internal/cdf"
1212
"github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors"
13+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality"
1314
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/zonal"
1415
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account"
1516
"github.com/scaleway/terraform-provider-scaleway/v2/internal/transport"
@@ -176,7 +177,7 @@ func ResourceImage() *schema.Resource {
176177
}
177178

178179
func ResourceInstanceImageCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
179-
instanceAPI, zone, err := newAPIWithZone(d, m)
180+
api, zone, err := instanceAndBlockAPIWithZone(d, m)
180181
if err != nil {
181182
return diag.FromErr(err)
182183
}
@@ -192,11 +193,7 @@ func ResourceInstanceImageCreate(ctx context.Context, d *schema.ResourceData, m
192193

193194
extraVolumesIDs, volumesExist := d.GetOk("additional_volume_ids")
194195
if volumesExist {
195-
snapResponses, err := getSnapshotsFromIDs(ctx, extraVolumesIDs.([]interface{}), instanceAPI)
196-
if err != nil {
197-
return diag.FromErr(err)
198-
}
199-
req.ExtraVolumes = expandImageExtraVolumesTemplates(snapResponses)
196+
req.ExtraVolumes = expandImageExtraVolumesTemplates(locality.ExpandIDs(extraVolumesIDs))
200197
}
201198
tags, tagsExist := d.GetOk("tags")
202199
if tagsExist {
@@ -206,14 +203,14 @@ func ResourceInstanceImageCreate(ctx context.Context, d *schema.ResourceData, m
206203
req.Public = types.ExpandBoolPtr(types.GetBool(d, "public"))
207204
}
208205

209-
res, err := instanceAPI.CreateImage(req, scw.WithContext(ctx))
206+
res, err := api.CreateImage(req, scw.WithContext(ctx))
210207
if err != nil {
211208
return diag.FromErr(err)
212209
}
213210

214211
d.SetId(zonal.NewIDString(zone, res.Image.ID))
215212

216-
_, err = instanceAPI.WaitForImage(&instanceSDK.WaitForImageRequest{
213+
_, err = api.WaitForImage(&instanceSDK.WaitForImageRequest{
217214
ImageID: res.Image.ID,
218215
Zone: zone,
219216
RetryInterval: transport.DefaultWaitRetryInterval,
@@ -262,7 +259,7 @@ func ResourceInstanceImageRead(ctx context.Context, d *schema.ResourceData, m in
262259
}
263260

264261
func ResourceInstanceImageUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
265-
instanceAPI, zone, id, err := NewAPIWithZoneAndID(m, d.Id())
262+
api, zone, id, err := instanceAndBlockAPIWithZoneAndID(m, d.Id())
266263
if err != nil {
267264
return diag.FromErr(err)
268265
}
@@ -283,7 +280,7 @@ func ResourceInstanceImageUpdate(ctx context.Context, d *schema.ResourceData, m
283280
}
284281
req.Tags = types.ExpandUpdatedStringsPtr(d.Get("tags"))
285282

286-
image, err := instanceAPI.GetImage(&instanceSDK.GetImageRequest{
283+
image, err := api.GetImage(&instanceSDK.GetImageRequest{
287284
Zone: zone,
288285
ImageID: id,
289286
}, scw.WithContext(ctx))
@@ -292,11 +289,7 @@ func ResourceInstanceImageUpdate(ctx context.Context, d *schema.ResourceData, m
292289
}
293290

294291
if d.HasChange("additional_volume_ids") {
295-
snapResponses, err := getSnapshotsFromIDs(ctx, d.Get("additional_volume_ids").([]interface{}), instanceAPI)
296-
if err != nil {
297-
return diag.FromErr(err)
298-
}
299-
req.ExtraVolumes = expandImageExtraVolumesUpdateTemplates(snapResponses)
292+
req.ExtraVolumes = expandImageExtraVolumesUpdateTemplates(locality.ExpandIDs(d.Get("additional_volume_ids")))
300293
} else {
301294
volTemplate := map[string]*instanceSDK.VolumeImageUpdateTemplate{}
302295
for key, vol := range image.Image.ExtraVolumes {
@@ -315,17 +308,17 @@ func ResourceInstanceImageUpdate(ctx context.Context, d *schema.ResourceData, m
315308
req.Arch = image.Image.Arch
316309
}
317310

318-
_, err = waitForImage(ctx, instanceAPI, zone, id, d.Timeout(schema.TimeoutUpdate))
311+
_, err = waitForImage(ctx, api.API, zone, id, d.Timeout(schema.TimeoutUpdate))
319312
if err != nil {
320313
return diag.FromErr(err)
321314
}
322315

323-
_, err = instanceAPI.UpdateImage(req, scw.WithContext(ctx))
316+
_, err = api.UpdateImage(req, scw.WithContext(ctx))
324317
if err != nil {
325318
return diag.FromErr(fmt.Errorf("couldn't update image: %s", err))
326319
}
327320

328-
_, err = waitForImage(ctx, instanceAPI, zone, id, d.Timeout(schema.TimeoutUpdate))
321+
_, err = waitForImage(ctx, api.API, zone, id, d.Timeout(schema.TimeoutUpdate))
329322
if err != nil {
330323
return diag.FromErr(err)
331324
}

internal/services/instance/image_test.go

+95
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,101 @@ func TestAccImage_BlockVolume(t *testing.T) {
109109
})
110110
}
111111

112+
func TestAccImage_ExternalBlockVolume(t *testing.T) {
113+
tt := acctest.NewTestTools(t)
114+
defer tt.Cleanup()
115+
resource.ParallelTest(t, resource.TestCase{
116+
PreCheck: func() { acctest.PreCheck(t) },
117+
ProviderFactories: tt.ProviderFactories,
118+
CheckDestroy: resource.ComposeTestCheckFunc(
119+
isImageDestroyed(tt),
120+
isSnapshotDestroyed(tt),
121+
isVolumeDestroyed(tt),
122+
),
123+
Steps: []resource.TestStep{
124+
{
125+
Config: `
126+
resource "scaleway_block_volume" "main" {
127+
size_in_gb = 50
128+
iops = 5000
129+
}
130+
131+
resource "scaleway_block_snapshot" "main" {
132+
volume_id = scaleway_block_volume.main.id
133+
}
134+
`,
135+
},
136+
{
137+
Config: `
138+
resource "scaleway_block_volume" "main" {
139+
size_in_gb = 50
140+
iops = 5000
141+
}
142+
143+
resource "scaleway_block_volume" "additional1" {
144+
size_in_gb = 50
145+
iops = 5000
146+
}
147+
148+
resource "scaleway_block_snapshot" "main" {
149+
volume_id = scaleway_block_volume.main.id
150+
}
151+
152+
resource "scaleway_block_snapshot" "additional1" {
153+
volume_id = scaleway_block_volume.additional1.id
154+
}
155+
156+
resource "scaleway_instance_image" "main" {
157+
name = "tf-test-image-external-block-volume"
158+
root_volume_id = scaleway_block_snapshot.main.id
159+
additional_volume_ids = [scaleway_block_snapshot.additional1.id]
160+
}
161+
`,
162+
Check: resource.ComposeTestCheckFunc(
163+
instancechecks.DoesImageExists(tt, "scaleway_instance_image.main"),
164+
resource.TestCheckResourceAttrPair("scaleway_instance_image.main", "root_volume_id", "scaleway_block_snapshot.main", "id"),
165+
resource.TestCheckResourceAttr("scaleway_instance_image.main", "architecture", "x86_64"),
166+
resource.TestCheckResourceAttr("scaleway_instance_image.main", "additional_volume_ids.#", "1"),
167+
resource.TestCheckResourceAttrPair("scaleway_instance_image.main", "additional_volume_ids.0", "scaleway_block_snapshot.additional1", "id"),
168+
),
169+
},
170+
{
171+
Config: `
172+
resource "scaleway_block_volume" "main" {
173+
size_in_gb = 50
174+
iops = 5000
175+
}
176+
177+
resource "scaleway_block_volume" "additional1" {
178+
size_in_gb = 50
179+
iops = 5000
180+
}
181+
182+
resource "scaleway_block_snapshot" "main" {
183+
volume_id = scaleway_block_volume.main.id
184+
}
185+
186+
resource "scaleway_block_snapshot" "additional1" {
187+
volume_id = scaleway_block_volume.additional1.id
188+
}
189+
190+
resource "scaleway_instance_image" "main" {
191+
name = "tf-test-image-external-block-volume"
192+
root_volume_id = scaleway_block_snapshot.main.id
193+
additional_volume_ids = []
194+
}
195+
`,
196+
Check: resource.ComposeTestCheckFunc(
197+
instancechecks.DoesImageExists(tt, "scaleway_instance_image.main"),
198+
resource.TestCheckResourceAttrPair("scaleway_instance_image.main", "root_volume_id", "scaleway_block_snapshot.main", "id"),
199+
resource.TestCheckResourceAttr("scaleway_instance_image.main", "architecture", "x86_64"),
200+
resource.TestCheckResourceAttr("scaleway_instance_image.main", "additional_volume_ids.#", "0"),
201+
),
202+
},
203+
},
204+
})
205+
}
206+
112207
func TestAccImage_Server(t *testing.T) {
113208
tt := acctest.NewTestTools(t)
114209
defer tt.Cleanup()

0 commit comments

Comments
 (0)