Skip to content

Commit d20c1ec

Browse files
committed
add tests for zone and backup, lint, naming nits
1 parent d2f2d80 commit d20c1ec

File tree

8 files changed

+498
-92
lines changed

8 files changed

+498
-92
lines changed

internal/services/instance/action_create_snapshot.go

Lines changed: 102 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import (
88
"github.com/hashicorp/terraform-plugin-framework/action/schema"
99
"github.com/hashicorp/terraform-plugin-framework/types"
1010
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
11+
block "github.com/scaleway/scaleway-sdk-go/api/block/v1alpha1"
1112
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
1213
"github.com/scaleway/scaleway-sdk-go/scw"
1314
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality"
1415
"github.com/scaleway/terraform-provider-scaleway/v2/internal/meta"
16+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/instance/instancehelpers"
1517
)
1618

1719
var (
@@ -20,7 +22,7 @@ var (
2022
)
2123

2224
type CreateSnapshot struct {
23-
instanceAPI *instance.API
25+
blockAndInstanceAPI *instancehelpers.BlockAndInstanceAPI
2426
}
2527

2628
func (c *CreateSnapshot) Configure(_ context.Context, req action.ConfigureRequest, resp *action.ConfigureResponse) {
@@ -39,7 +41,7 @@ func (c *CreateSnapshot) Configure(_ context.Context, req action.ConfigureReques
3941
}
4042

4143
client := m.ScwClient()
42-
c.instanceAPI = instance.NewAPI(client)
44+
c.blockAndInstanceAPI = instancehelpers.NewBlockAndInstanceAPI(client)
4345
}
4446

4547
func (c *CreateSnapshot) Metadata(_ context.Context, req action.MetadataRequest, resp *action.MetadataResponse) {
@@ -80,7 +82,7 @@ func (c *CreateSnapshot) Schema(_ context.Context, _ action.SchemaRequest, resp
8082
},
8183
"wait": schema.BoolAttribute{
8284
Optional: true,
83-
Description: "Wait for snapshotting operation to be finished",
85+
Description: "Wait for snapshotting operation to be completed",
8486
},
8587
},
8688
}
@@ -95,9 +97,9 @@ func (c *CreateSnapshot) Invoke(ctx context.Context, req action.InvokeRequest, r
9597
return
9698
}
9799

98-
if c.instanceAPI == nil {
100+
if c.blockAndInstanceAPI == nil {
99101
resp.Diagnostics.AddError(
100-
"Unconfigured instanceAPI",
102+
"Unconfigured instanceAPI / blockAPI",
101103
"The action was not properly configured. The Scaleway client is missing. "+
102104
"This is usually a bug in the provider. Please report it to the maintainers.",
103105
)
@@ -121,44 +123,113 @@ func (c *CreateSnapshot) Invoke(ctx context.Context, req action.InvokeRequest, r
121123
}
122124
}
123125

124-
actionReq := &instance.CreateSnapshotRequest{
125-
VolumeID: &volumeID,
126+
volume, err := c.blockAndInstanceAPI.GetUnknownVolume(&instancehelpers.GetUnknownVolumeRequest{
127+
VolumeID: volumeID,
126128
Zone: scw.Zone(zone),
127-
}
129+
}, scw.WithContext(ctx))
130+
if err != nil {
131+
resp.Diagnostics.AddError(
132+
"could not find volume "+data.VolumeID.ValueString(),
133+
err.Error(),
134+
)
128135

129-
if !data.Name.IsNull() {
130-
actionReq.Name = data.Name.ValueString()
136+
return
131137
}
132138

133-
if len(data.Tags.Elements()) > 0 {
134-
tags := make([]string, 0, len(data.Tags.Elements()))
139+
switch volume.InstanceVolumeType {
140+
case instance.VolumeVolumeTypeLSSD:
141+
actionReq := &instance.CreateSnapshotRequest{
142+
VolumeID: &volumeID,
143+
Zone: scw.Zone(zone),
144+
}
135145

136-
diags := data.Tags.ElementsAs(ctx, &tags, false)
137-
if diags.HasError() {
138-
resp.Diagnostics.Append(diags...)
139-
} else {
140-
actionReq.Tags = &tags
146+
if !data.Name.IsNull() {
147+
actionReq.Name = data.Name.ValueString()
141148
}
142-
}
143149

144-
snapshot, err := c.instanceAPI.CreateSnapshot(actionReq, scw.WithContext(ctx))
145-
if err != nil {
146-
resp.Diagnostics.AddError(
147-
"error creating snapshot",
148-
fmt.Sprintf("%s", err))
150+
if len(data.Tags.Elements()) > 0 {
151+
tags := make([]string, 0, len(data.Tags.Elements()))
152+
153+
diags := data.Tags.ElementsAs(ctx, &tags, false)
154+
if diags.HasError() {
155+
resp.Diagnostics.Append(diags...)
156+
} else {
157+
actionReq.Tags = &tags
158+
}
159+
}
160+
161+
snapshot, err := c.blockAndInstanceAPI.CreateSnapshot(actionReq, scw.WithContext(ctx))
162+
if err != nil {
163+
resp.Diagnostics.AddError(
164+
"error creating instance snapshot",
165+
err.Error())
149166

150167
return
151168
}
152169

153-
if data.Wait.ValueBool() {
154-
_, errWait := c.instanceAPI.WaitForSnapshot(&instance.WaitForSnapshotRequest{
155-
SnapshotID: snapshot.Snapshot.ID,
156-
Zone: scw.Zone(zone),
157-
}, scw.WithContext(ctx))
158-
if errWait != nil {
170+
if data.Wait.ValueBool() {
171+
_, errWait := c.blockAndInstanceAPI.WaitForSnapshot(&instance.WaitForSnapshotRequest{
172+
SnapshotID: snapshot.Snapshot.ID,
173+
Zone: scw.Zone(zone),
174+
}, scw.WithContext(ctx))
175+
if errWait != nil {
176+
resp.Diagnostics.AddError(
177+
"error waiting for instance snapshot",
178+
err.Error())
179+
}
180+
}
181+
case instance.VolumeVolumeTypeSbsVolume:
182+
api := c.blockAndInstanceAPI.BlockAPI
183+
184+
actionReq := &block.CreateSnapshotRequest{
185+
VolumeID: volumeID,
186+
Zone: scw.Zone(zone),
187+
}
188+
189+
if !data.Name.IsNull() {
190+
actionReq.Name = data.Name.ValueString()
191+
}
192+
193+
if len(data.Tags.Elements()) > 0 {
194+
tags := make([]string, 0, len(data.Tags.Elements()))
195+
196+
diags := data.Tags.ElementsAs(ctx, &tags, false)
197+
if diags.HasError() {
198+
resp.Diagnostics.Append(diags...)
199+
} else {
200+
actionReq.Tags = tags
201+
}
202+
}
203+
204+
snapshot, err := api.CreateSnapshot(actionReq, scw.WithContext(ctx))
205+
if err != nil {
159206
resp.Diagnostics.AddError(
160-
"error waiting for snapshot",
161-
fmt.Sprintf("%s", err))
207+
"error creating block snapshot",
208+
err.Error())
209+
210+
return
211+
}
212+
213+
if data.Wait.ValueBool() {
214+
_, errWait := api.WaitForSnapshot(&block.WaitForSnapshotRequest{
215+
SnapshotID: snapshot.ID,
216+
Zone: scw.Zone(zone),
217+
}, scw.WithContext(ctx))
218+
if errWait != nil {
219+
resp.Diagnostics.AddError(
220+
"error waiting for block snapshot",
221+
err.Error())
222+
}
162223
}
224+
case instance.VolumeVolumeTypeScratch:
225+
resp.Diagnostics.AddError(
226+
"invalid volume type",
227+
"cannot create snapshot from a volume of type scratch",
228+
)
229+
default:
230+
resp.Diagnostics.AddError(
231+
"invalid volume type",
232+
fmt.Sprintf("unknown volume type %q", volume.InstanceVolumeType),
233+
)
163234
}
164235
}

internal/services/instance/action_create_snapshot_test.go

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func TestAccAction_InstanceCreateSnapshot_Local(t *testing.T) {
4242
{
4343
Config: fmt.Sprintf(`
4444
resource "scaleway_instance_server" "main" {
45-
name = "test-terraform-action-instance-create-snapshot"
45+
name = "test-tf-action-instance-create-snapshot-local"
4646
type = "DEV1-S"
4747
image = "ubuntu_jammy"
4848
@@ -83,7 +83,7 @@ func TestAccAction_InstanceCreateSnapshot_Local(t *testing.T) {
8383
{
8484
Config: fmt.Sprintf(`
8585
resource "scaleway_instance_server" "main" {
86-
name = "test-terraform-action-instance-create-snapshot"
86+
name = "test-tf-action-instance-create-snapshot-local"
8787
type = "DEV1-S"
8888
image = "ubuntu_jammy"
8989
tags = [ "add", "tags", "to", "trigger", "update" ]
@@ -142,13 +142,12 @@ func TestAccAction_InstanceCreateSnapshot_Scratch(t *testing.T) {
142142

143143
resource.ParallelTest(t, resource.TestCase{
144144
ProtoV6ProviderFactories: tt.ProviderFactories,
145-
CheckDestroy: resource.ComposeTestCheckFunc(
146-
instancechecks.IsVolumeDestroyed(tt),
147-
),
145+
CheckDestroy: instancechecks.IsServerDestroyed(tt),
148146
Steps: []resource.TestStep{
149147
{
150148
Config: fmt.Sprintf(`
151149
resource "scaleway_instance_volume" "scratch" {
150+
name = "test-tf-action-instance-create-snapshot-scratch"
152151
type = "%s"
153152
size_in_gb = 50
154153
@@ -172,6 +171,71 @@ func TestAccAction_InstanceCreateSnapshot_Scratch(t *testing.T) {
172171
})
173172
}
174173

174+
func TestAccAction_InstanceCreateSnapshot_Zone(t *testing.T) {
175+
if acctest.IsRunningOpenTofu() {
176+
t.Skip("Skipping TestAccAction_InstanceCreateSnapshot_Zone because action are not yet supported on OpenTofu")
177+
}
178+
179+
tt := acctest.NewTestTools(t)
180+
defer tt.Cleanup()
181+
182+
localVolumeType := instanceSDK.VolumeVolumeTypeLSSD
183+
184+
resource.ParallelTest(t, resource.TestCase{
185+
ProtoV6ProviderFactories: tt.ProviderFactories,
186+
CheckDestroy: resource.ComposeTestCheckFunc(
187+
instancechecks.IsServerDestroyed(tt),
188+
destroyUntrackedSnapshots(tt, "data.scaleway_instance_volume.main"),
189+
),
190+
Steps: []resource.TestStep{
191+
{
192+
Config: fmt.Sprintf(`
193+
resource "scaleway_instance_server" "main" {
194+
name = "test-tf-action-instance-create-snapshot-zone"
195+
type = "DEV1-S"
196+
image = "ubuntu_jammy"
197+
zone = "fr-par-2"
198+
199+
root_volume {
200+
volume_type = "%s"
201+
size_in_gb = 20
202+
}
203+
204+
lifecycle {
205+
action_trigger {
206+
events = [after_create]
207+
actions = [action.scaleway_instance_create_snapshot.main]
208+
}
209+
}
210+
}
211+
212+
data "scaleway_instance_volume" "main" {
213+
volume_id = scaleway_instance_server.main.root_volume.0.volume_id
214+
zone = "fr-par-2"
215+
}
216+
217+
action "scaleway_instance_create_snapshot" "main" {
218+
config {
219+
volume_id = scaleway_instance_server.main.root_volume.0.volume_id
220+
wait = true
221+
}
222+
}`, localVolumeType),
223+
},
224+
{
225+
RefreshState: true,
226+
Check: resource.ComposeTestCheckFunc(
227+
instancechecks.IsVolumePresent(tt, "data.scaleway_instance_volume.main"),
228+
resource.TestCheckResourceAttr("scaleway_instance_server.main", "zone", "fr-par-2"),
229+
checkSnapshot(tt, "data.scaleway_instance_volume.main", snapshotSpecsCheck{
230+
Size: scw.SizePtr(20 * scw.GB),
231+
Type: &localVolumeType,
232+
}),
233+
),
234+
},
235+
},
236+
})
237+
}
238+
175239
func snapshotMatchesExpectedSpecs(snapshot instanceSDK.Snapshot, expected snapshotSpecsCheck) bool {
176240
if expected.Name != nil && *expected.Name != snapshot.Name {
177241
return false

0 commit comments

Comments
 (0)