Skip to content

Commit

Permalink
Add fly volume snapshot create (#3087)
Browse files Browse the repository at this point in the history
This new command is used to snapshot volumes on-demand.
  • Loading branch information
kzys authored Jan 13, 2024
1 parent a88e953 commit 59a16d0
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 8 deletions.
1 change: 1 addition & 0 deletions api/volume_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,5 @@ type VolumeSnapshot struct {
Size int `json:"size"`
Digest string `json:"digest"`
CreatedAt time.Time `json:"created_at"`
Status string `json:"status"`
}
9 changes: 6 additions & 3 deletions flaps/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ const (
volumeCreate
volumetUpdate
volumeGet
volumeSnapshot
volumeSnapshotCreate
volumeSnapshotList
volumeExtend
volumeDelete
)
Expand Down Expand Up @@ -79,8 +80,10 @@ func (a *flapsAction) String() string {
return "volume_list"
case volumetUpdate:
return "volume_update"
case volumeSnapshot:
return "volume_snapshot"
case volumeSnapshotCreate:
return "volume_snapshot_create"
case volumeSnapshotList:
return "volume_snapshot_list"
case volumeExtend:
return "volume_extend"
case volumeDelete:
Expand Down
13 changes: 12 additions & 1 deletion flaps/flaps_volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,24 @@ func (f *Client) GetVolumeSnapshots(ctx context.Context, volumeId string) ([]api

out := make([]api.VolumeSnapshot, 0)

err := f.sendRequestVolumes(ctx, volumeSnapshot, http.MethodGet, getVolumeSnapshotsEndpoint, nil, &out, nil)
err := f.sendRequestVolumes(ctx, volumeSnapshotList, http.MethodGet, getVolumeSnapshotsEndpoint, nil, &out, nil)
if err != nil {
return nil, fmt.Errorf("failed to get volume %s snapshots: %w", volumeId, err)
}
return out, nil
}

func (f *Client) CreateVolumeSnapshot(ctx context.Context, volumeId string) error {
err := f.sendRequestVolumes(
ctx, volumeSnapshotCreate, http.MethodPost, fmt.Sprintf("/%s/snapshots", volumeId),
nil, nil, nil,
)
if err != nil {
return fmt.Errorf("failed to snapshot %s: %w", volumeId, err)
}
return nil
}

type ExtendVolumeRequest struct {
SizeGB int `json:"size_gb"`
}
Expand Down
1 change: 0 additions & 1 deletion internal/command/volumes/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ func newCreate() *cobra.Command {
command.RequireSession,
command.RequireAppName,
)

cmd.Args = cobra.ExactArgs(1)

flag.Add(cmd,
Expand Down
57 changes: 57 additions & 0 deletions internal/command/volumes/snapshots/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package snapshots

import (
"context"
"fmt"

"github.com/spf13/cobra"

"github.com/superfly/flyctl/client"
"github.com/superfly/flyctl/flaps"
"github.com/superfly/flyctl/internal/appconfig"
"github.com/superfly/flyctl/internal/command"
"github.com/superfly/flyctl/internal/flag"
)

func newCreate() *cobra.Command {
const (
short = "Snapshot a volume"
long = "Snapshot a volume\n"
usage = "create <volume-id>"
)

cmd := command.New(usage, short, long, create, command.RequireSession)
cmd.Args = cobra.ExactArgs(1)

flag.Add(cmd, flag.JSONOutput())
return cmd
}

func create(ctx context.Context) error {
var client = client.FromContext(ctx).API()

volumeId := flag.FirstArg(ctx)

appName := appconfig.NameFromContext(ctx)
if appName == "" {
n, err := client.GetAppNameFromVolume(ctx, volumeId)
if err != nil {
return err
}
appName = *n
}

flapsClient, err := flaps.NewFromAppName(ctx, appName)
if err != nil {
return err
}

err = flapsClient.CreateVolumeSnapshot(ctx, volumeId)
if err != nil {
return err
}

fmt.Printf("Scheduled to snapshot volume %s\n", volumeId)

return nil
}
20 changes: 17 additions & 3 deletions internal/command/volumes/snapshots/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"sort"
"strconv"
"time"

"github.com/dustin/go-humanize"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -40,6 +41,13 @@ func newList() *cobra.Command {
return cmd
}

func timeToString(t time.Time) string {
if t.IsZero() {
return ""
}
return humanize.Time(t)
}

func runList(ctx context.Context) error {
var (
io = iostreams.FromContext(ctx)
Expand Down Expand Up @@ -84,12 +92,18 @@ func runList(ctx context.Context) error {

rows := make([][]string, 0, len(snapshots))
for _, snapshot := range snapshots {
id := snapshot.ID
if id == "" {
id = "(pending)"
}

rows = append(rows, []string{
snapshot.ID,
id,
snapshot.Status,
strconv.Itoa(snapshot.Size),
humanize.Time(snapshot.CreatedAt),
timeToString(snapshot.CreatedAt),
})
}

return render.Table(io.Out, "Snapshots", rows, "ID", "Size", "Created At")
return render.Table(io.Out, "Snapshots", rows, "ID", "Status", "Size", "Created At")
}
1 change: 1 addition & 0 deletions internal/command/volumes/snapshots/snapshots.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func New() *cobra.Command {

snapshots.AddCommand(
newList(),
newCreate(),
)

return snapshots
Expand Down

0 comments on commit 59a16d0

Please sign in to comment.