1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
package flymachines
import (
"context"
"fmt"
"net/http"
"time"
)
type Volume struct {
ID string `json:"id"`
Name string `json:"name"`
State string `json:"state"`
SizeGB int `json:"size_gb"`
Region string `json:"region"`
Zone string `json:"zone"`
Encrypted bool `json:"encrypted"`
AttachedAllocID string `json:"attached_alloc_id"`
AttachedMachineID string `json:"attached_machine_id"`
CreatedAt time.Time `json:"created_at"`
Blocks int `json:"blocks"`
BlockSize int `json:"block_size"`
BlocksAvail int `json:"blocks_avail"`
BlocksFree int `json:"blocks_free"`
FSType string `json:"fs_type"`
SnapshotRetention int `json:"snapshot_retention"`
HostDedicationKey string `json:"host_dedication_key,omitempty"`
}
func (c *Client) GetVolumes(ctx context.Context, appName string) ([]Volume, error) {
return doJSON[[]Volume](ctx, c, http.MethodGet, "/v1/apps/"+appName+"/volumes", http.StatusOK)
}
func (c *Client) GetVolume(ctx context.Context, appName, volumeID string) (*Volume, error) {
result, err := doJSON[Volume](ctx, c, http.MethodGet, "/v1/apps/"+appName+"/volumes/"+volumeID, http.StatusOK)
if err != nil {
return nil, fmt.Errorf("flymachines: can't decode GetVolume response: %w", err)
}
return &result, nil
}
type CreateVolume struct {
Compute *MachineGuest `json:"compute,omitempty"`
Encrypted bool `json:"encrypted,omitempty"`
FSType string `json:"fs_type,omitempty"`
MachinesOnly bool `json:"machines_only,omitempty"`
Name string `json:"name,omitempty"`
Region string `json:"region,omitempty"`
RequireUniqueZone bool `json:"require_unique_zone"`
SizeGB int `json:"size_gb,omitempty"`
SnapshotID string `json:"snapshot_id,omitempty"`
SnapshotRetention int `json:"snapshot_retention"`
SourceVolumeID string `json:"source_volume_id,omitempty"`
}
func (cv CreateVolume) Fork(vol *Volume) CreateVolume {
cv.SourceVolumeID = vol.ID
cv.SnapshotRetention = vol.SnapshotRetention
cv.FSType = vol.FSType
return cv
}
func (c *Client) CreateVolume(ctx context.Context, appName string, cv CreateVolume) (*Volume, error) {
result, err := doJSONBody[CreateVolume, Volume](ctx, c, http.MethodPost, "/v1/apps/"+appName+"/volumes", cv, http.StatusOK)
if err != nil {
return nil, fmt.Errorf("flymachines: can't decode CreateVolume response: %w", err)
}
return &result, nil
}
func (c *Client) DeleteVolume(ctx context.Context, appName, volumeID string) error {
err := c.doRequestNoResponse(ctx, http.MethodDelete, "/v1/apps/"+appName+"/volumes/"+volumeID)
if err != nil {
return err
}
return nil
}
type ExtendVolumeResponse struct {
NeedsRestart bool `json:"needs_restart"`
Volume Volume `json:"volume"`
}
func (c *Client) ExtendVolume(ctx context.Context, appName, voluleID string, sizeGB int) (*ExtendVolumeResponse, error) {
type req struct {
SizeGB int `json:"size_gb"`
}
result, err := doJSONBody[req, ExtendVolumeResponse](ctx, c, http.MethodPost, "/v1/apps/"+appName+"/volumes/"+voluleID+"/extend", req{sizeGB}, http.StatusOK)
if err != nil {
return nil, fmt.Errorf("flymachines: can't decode ExtendVolume response: %w", err)
}
return &result, nil
}
type Snapshot struct {
CreatedAt time.Time `json:"created_at"`
Digest string `json:"digest"`
ID string `json:"id"`
Size int `json:"size"`
}
func (c *Client) ListVolumeSnapshots(ctx context.Context, appName, volumeID string) ([]Snapshot, error) {
return doJSON[[]Snapshot](ctx, c, http.MethodGet, "/v1/apps/"+appName+"/volumes/"+volumeID+"/snapshots", http.StatusOK)
}
|