Skip to content

Commit d957ca7

Browse files
feat(jobs): move snapshots to s3
1 parent 8514601 commit d957ca7

File tree

5 files changed

+145
-0
lines changed

5 files changed

+145
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Using apline/golang image
2+
FROM golang:1.25-alpine
3+
4+
# Set destination for COPY
5+
WORKDIR /app
6+
7+
# Copy required files
8+
COPY go.mod ./
9+
COPY go.sum ./
10+
COPY main.go ./
11+
12+
# Build the executable
13+
RUN go build -o /jobs-snapshot-s3
14+
15+
# Run the executable
16+
ENTRYPOINT [ "/jobs-snapshot-s3" ]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Serverless Jobs to move snapshots to S3

jobs/snapshot-s3-archiver/go.mod

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module github.com/scaleway/serverless-examples/jobs/instances-snapshot
2+
3+
go 1.25
4+
5+
require github.com/scaleway/scaleway-sdk-go v1.0.0-beta.34
6+
7+
require (
8+
github.com/kr/pretty v0.3.1 // indirect
9+
github.com/rogpeppe/go-internal v1.14.1 // indirect
10+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
11+
gopkg.in/yaml.v2 v2.4.0 // indirect
12+
)

jobs/snapshot-s3-archiver/go.sum

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
2+
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
3+
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
4+
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
5+
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
6+
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
7+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
8+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
9+
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
10+
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
11+
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
12+
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
13+
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.34 h1:48+VFHsyVcAHIN2v1Ao9v1/RkjJS5AwctFucBrfYNIA=
14+
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.34/go.mod h1:zFWiHphneiey3s8HOtAEnGrRlWivNaxW5T6d5Xfco7g=
15+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
16+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
17+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
18+
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
19+
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

jobs/snapshot-s3-archiver/main.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
8+
"github.com/scaleway/scaleway-sdk-go/scw"
9+
)
10+
11+
// Environment variable constants used to configure the Scaleway API client.
12+
// These must be set in the environment for the application to authenticate and interact with Scaleway services.
13+
const (
14+
// envOrgID is the Scaleway Organization ID, used for billing and resource ownership (legacy; prefer Project ID).
15+
envOrgID = "SCW_DEFAULT_ORGANIZATION_ID"
16+
17+
// envAccessKey is the API access key for authenticating requests to Scaleway.
18+
envAccessKey = "SCW_ACCESS_KEY"
19+
20+
// envSecretKey is the secret key associated with the access key, used for signing requests.
21+
envSecretKey = "SCW_SECRET_KEY"
22+
23+
// envProjectID is the Scaleway Project ID, which groups resources and is the preferred way to organize infrastructure.
24+
envProjectID = "SCW_DEFAULT_PROJECT_ID"
25+
26+
// envZone specifies the geographical region/zone where resources will be created (e.g., fr-par-1).
27+
envZone = "SCW_ZONE"
28+
29+
// envBucket is a custom environment variable for specifying the name of an S3-compatible bucket.
30+
// This is not a standard Scaleway variable and is application-specific.
31+
envBucket = "SCW_BUCKET_NAME"
32+
)
33+
34+
func main() {
35+
fmt.Println("moving snapshots to s3...")
36+
37+
// Create a Scaleway client with credentials from environment variables.
38+
client, err := scw.NewClient(
39+
// Get your organization ID at https://console.scaleway.com/organization/settings
40+
scw.WithDefaultOrganizationID(os.Getenv(envOrgID)),
41+
42+
// Get your credentials at https://console.scaleway.com/iam/api-keys
43+
scw.WithAuth(os.Getenv(envAccessKey), os.Getenv(envSecretKey)),
44+
45+
// Set the default project ID to organize resources under a specific project
46+
scw.WithDefaultProjectID(os.Getenv(envProjectID)),
47+
48+
// Set the default zone where resources such as block volumes and snapshots are located
49+
scw.WithDefaultZone(scw.Zone(os.Getenv(envZone))),
50+
)
51+
if err != nil {
52+
panic(err)
53+
}
54+
55+
instanceAPI := instance.NewAPI(client)
56+
57+
snapList, err := instanceAPI.ListSnapshots(&instance.ListSnapshotsRequest{}, scw.WithAllPages())
58+
if err != nil {
59+
panic(err)
60+
}
61+
62+
fmt.Printf("number of snapshots: %d\n", snapList.TotalCount)
63+
64+
for _, snapshot := range snapList.Snapshots {
65+
fmt.Printf("snap %s\n", snapshot.Name)
66+
67+
if snapshot.State == instance.SnapshotStateAvailable {
68+
fmt.Printf("Exporting snapshot %s (ID: %s) to bucket %s...\n", snapshot.Name, snapshot.ID, os.Getenv(envBucket))
69+
70+
snap, err := instanceAPI.ExportSnapshot(&instance.ExportSnapshotRequest{
71+
SnapshotID: snapshot.ID,
72+
Bucket: os.Getenv(envBucket),
73+
Key: snapshot.Name + ".qcow2",
74+
})
75+
if err != nil {
76+
fmt.Printf("Failed to export snapshot %s: %v\n", snapshot.Name, err)
77+
78+
continue
79+
}
80+
81+
fmt.Printf("Successfully started export of %s to %s/%s\n", snap.Task.ID, os.Getenv(envBucket), snap.Task.Description)
82+
} else {
83+
fmt.Printf("Skipping snapshot %s (ID: %s) - status is %s, not available\n", snapshot.Name, snapshot.ID, snapshot.State.String())
84+
}
85+
}
86+
}
87+
88+
// Check for mandatory variables before starting to work.
89+
func init() {
90+
mandatoryVariables := [...]string{envOrgID, envAccessKey, envSecretKey, envZone, envProjectID, envBucket}
91+
92+
for idx := range mandatoryVariables {
93+
if os.Getenv(mandatoryVariables[idx]) == "" {
94+
panic("missing environment variable " + mandatoryVariables[idx])
95+
}
96+
}
97+
}

0 commit comments

Comments
 (0)