Skip to content

Commit 40022f0

Browse files
authored
SSH signed commit (#3201)
feat(block): support export to s3 feat(block): support export to s3 fix linter signed with SSH
1 parent 3c70114 commit 40022f0

File tree

6 files changed

+12909
-76
lines changed

6 files changed

+12909
-76
lines changed

docs/resources/block_snapshot.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,52 @@ resource "scaleway_block_snapshot" "block_snapshot" {
2929
}
3030
```
3131

32+
### How to import from Object Storage
33+
34+
```terraform
35+
resource "scaleway_object_bucket" "my-import-bucket" {
36+
name = "snapshot-bucket-to-import"
37+
}
38+
39+
resource "scaleway_object" "qcow-object" {
40+
bucket = scaleway_object_bucket.snapshot-bucket.name
41+
key = "my-snapshot.qcow2"
42+
file = "imported-snapshot/snapshot.qcow2"
43+
}
44+
resource "scaleway_block_volume" "imported" {
45+
iops = 5000
46+
name = "imported-from-qcow"
47+
48+
import {
49+
bucket = "my-import-bucket"
50+
key = "imported-snapshot/snapshot.qcow2"
51+
}
52+
}
53+
```
54+
55+
### How to export to Object Storage
56+
57+
```terraform
58+
resource "scaleway_object_bucket" "my-import-bucket" {
59+
name = "snapshot-bucket-to-import"
60+
}
61+
62+
resource "scaleway_object" "qcow-object" {
63+
bucket = scaleway_object_bucket.snapshot-bucket.name
64+
key = "export/my-snapshot.qcow2"
65+
}
66+
67+
resource "scaleway_block_volume" "to_export" {
68+
iops = 5000
69+
name = "to-export"
70+
71+
export {
72+
bucket = "snapshot-bucket-to-import"
73+
key = "exports/my-snapshot.qcow2"
74+
}
75+
}
76+
```
77+
3278
## Argument Reference
3379

3480
This section lists the arguments that are supported:
@@ -38,6 +84,12 @@ This section lists the arguments that are supported:
3884
- `zone` - (Defaults to the zone specified in the [provider configuration](../index.md#zone)). The [zone](../guides/regions_and_zones.md#zones) in which the snapshot should be created.
3985
- `project_id` - (Defaults to the Project ID specified in the [provider configuration](../index.md#project_id)). The ID of the Scaleway Project the snapshot is associated with.
4086
- `tags` - (Optional) A list of tags to apply to the snapshot.
87+
- `import` - (Optional) Use this block to import a QCOW image from Object Storage to create a volume.
88+
- `bucket` – (Required) The name of the bucket containing the QCOW file.
89+
- `key` – (Required) The key of the QCOW file within the bucket.
90+
- `export` - (Optional) Use this block to export the volume as a QCOW file to Object Storage.
91+
- `bucket` – (Required) The name of the bucket where the QCOW file will be saved.
92+
- `key` – (Required) The desired key (path) for the QCOW file within the bucket.
4193

4294
## Attributes Reference
4395

internal/services/block/snapshot.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,30 @@ func ResourceSnapshot() *schema.Resource {
8484
Description: "Import snapshot from a qcow",
8585
ConflictsWith: []string{"volume_id"},
8686
},
87+
"export": {
88+
Type: schema.TypeList,
89+
MaxItems: 1,
90+
Elem: &schema.Resource{
91+
Schema: map[string]*schema.Schema{
92+
"bucket": {
93+
Type: schema.TypeString,
94+
Required: true,
95+
Description: "Bucket containing qcow",
96+
DiffSuppressFunc: dsf.Locality,
97+
StateFunc: func(i any) string {
98+
return regional.ExpandID(i.(string)).ID
99+
},
100+
},
101+
"key": {
102+
Type: schema.TypeString,
103+
Required: true,
104+
Description: "Key of the qcow file in the specified bucket",
105+
},
106+
},
107+
},
108+
Optional: true,
109+
Description: "Export snapshot to a qcow",
110+
},
87111
"zone": zonal.Schema(),
88112
"project_id": account.ProjectIDSchema(),
89113
},
@@ -132,6 +156,20 @@ func ResourceBlockSnapshotCreate(ctx context.Context, d *schema.ResourceData, m
132156
return diag.FromErr(err)
133157
}
134158

159+
if _, shouldExport := d.GetOk("export"); shouldExport {
160+
req := block.ExportSnapshotToObjectStorageRequest{
161+
Zone: zone,
162+
SnapshotID: snapshot.ID,
163+
Bucket: regional.ExpandID(d.Get("export.0.bucket")).ID,
164+
Key: d.Get("export.0.key").(string),
165+
}
166+
167+
_, err = api.ExportSnapshotToObjectStorage(&req, scw.WithContext(ctx))
168+
if err != nil {
169+
return diag.FromErr(err)
170+
}
171+
}
172+
135173
return ResourceBlockSnapshotRead(ctx, d, m)
136174
}
137175

@@ -201,6 +239,20 @@ func ResourceBlockSnapshotUpdate(ctx context.Context, d *schema.ResourceData, m
201239
return diag.FromErr(err)
202240
}
203241

242+
if shouldExport := d.HasChange("export"); shouldExport {
243+
req := block.ExportSnapshotToObjectStorageRequest{
244+
Zone: zone,
245+
SnapshotID: snapshot.ID,
246+
Bucket: regional.ExpandID(d.Get("export.0.bucket")).ID,
247+
Key: d.Get("export.0.key").(string),
248+
}
249+
250+
_, err = api.ExportSnapshotToObjectStorage(&req, scw.WithContext(ctx))
251+
if err != nil {
252+
return diag.FromErr(err)
253+
}
254+
}
255+
204256
return ResourceBlockSnapshotRead(ctx, d, m)
205257
}
206258

internal/services/block/snapshot_test.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,107 @@ func TestAccSnapshot_FromS3(t *testing.T) {
8585
},
8686
})
8787
}
88+
89+
func TestAccSnapshot_ToS3(t *testing.T) {
90+
tt := acctest.NewTestTools(t)
91+
defer tt.Cleanup()
92+
93+
bucketName := sdkacctest.RandomWithPrefix("test-acc-scaleway-export-block-snapshot")
94+
resource.ParallelTest(t, resource.TestCase{
95+
PreCheck: func() { acctest.PreCheck(t) },
96+
ProviderFactories: tt.ProviderFactories,
97+
CheckDestroy: resource.ComposeTestCheckFunc(
98+
blocktestfuncs.IsSnapshotDestroyed(tt),
99+
objectchecks.IsObjectDestroyed(tt),
100+
objectchecks.IsBucketDestroyed(tt),
101+
),
102+
Steps: []resource.TestStep{
103+
{
104+
Config: fmt.Sprintf(`
105+
resource scaleway_block_volume main {
106+
iops = 5000
107+
size_in_gb = 10
108+
}
109+
110+
resource "scaleway_object_bucket" "snapshot-bucket" {
111+
name = "%s"
112+
}
113+
114+
resource "scaleway_object" "qcow-object" {
115+
bucket = scaleway_object_bucket.snapshot-bucket.name
116+
key = "test-acc-export-block-snapshot-qcow2"
117+
content = "test"
118+
}
119+
120+
resource "scaleway_block_snapshot" "qcow-block-snapshot" {
121+
name = "test-acc-export-block-snapshot-qcow2"
122+
volume_id = scaleway_block_volume.main.id
123+
export {
124+
bucket = scaleway_object.qcow-object.bucket
125+
key = scaleway_object.qcow-object.key
126+
}
127+
}
128+
`, bucketName),
129+
Check: resource.ComposeTestCheckFunc(
130+
blocktestfuncs.IsSnapshotPresent(tt, "scaleway_block_snapshot.qcow-block-snapshot"),
131+
acctest.CheckResourceAttrUUID("scaleway_block_snapshot.qcow-block-snapshot", "id"),
132+
resource.TestCheckResourceAttr("scaleway_block_snapshot.qcow-block-snapshot", "name", "test-acc-export-block-snapshot-qcow2"),
133+
objectchecks.IsObjectExists(tt, "scaleway_object.qcow-object"),
134+
),
135+
},
136+
{
137+
Config: fmt.Sprintf(`
138+
resource scaleway_block_volume main {
139+
iops = 5000
140+
size_in_gb = 10
141+
}
142+
143+
resource "scaleway_object_bucket" "snapshot-bucket" {
144+
name = "%s"
145+
}
146+
147+
resource "scaleway_object" "qcow-object" {
148+
bucket = scaleway_object_bucket.snapshot-bucket.name
149+
key = "test-acc-export-block-snapshot-qcow2"
150+
content = "test"
151+
}
152+
153+
resource "scaleway_block_snapshot" "qcow-block-export-snapshot" {
154+
name = "test-acc-export-block-snapshot-qcow2"
155+
volume_id = scaleway_block_volume.main.id
156+
export {
157+
bucket = scaleway_object.qcow-object.bucket
158+
key = scaleway_object.qcow-object.key
159+
}
160+
}
161+
162+
resource "scaleway_block_snapshot" "qcow-block-import-snapshot" {
163+
name = "test-acc-block-snapshot-qcow2"
164+
import {
165+
bucket = scaleway_object.qcow-object.bucket
166+
key = scaleway_object.qcow-object.key
167+
}
168+
}
169+
170+
resource scaleway_block_volume new-volume {
171+
name = "test-block-volume-from-snapshot"
172+
iops = 5000
173+
snapshot_id = scaleway_block_snapshot.qcow-block-import-snapshot.id
174+
}
175+
176+
`, bucketName),
177+
Check: resource.ComposeTestCheckFunc(
178+
blocktestfuncs.IsSnapshotPresent(tt, "scaleway_block_snapshot.qcow-block-export-snapshot"),
179+
acctest.CheckResourceAttrUUID("scaleway_block_snapshot.qcow-block-export-snapshot", "id"),
180+
resource.TestCheckResourceAttr("scaleway_block_snapshot.qcow-block-export-snapshot", "name", "test-acc-export-block-snapshot-qcow2"),
181+
objectchecks.IsObjectExists(tt, "scaleway_object.qcow-object"),
182+
blocktestfuncs.IsSnapshotPresent(tt, "scaleway_block_snapshot.qcow-block-import-snapshot"),
183+
acctest.CheckResourceAttrUUID("scaleway_block_snapshot.qcow-block-import-snapshot", "id"),
184+
resource.TestCheckResourceAttr("scaleway_block_volume.new-volume", "size_in_gb", "10"),
185+
resource.TestCheckResourceAttr("scaleway_block_volume.new-volume", "iops", "5000"),
186+
resource.TestCheckResourceAttrPair("scaleway_block_volume.new-volume", "snapshot_id", "scaleway_block_snapshot.qcow-block-import-snapshot", "id"),
187+
),
188+
},
189+
},
190+
})
191+
}

0 commit comments

Comments
 (0)