1// 2// Copyright (c) 2018, Joyent, Inc. All rights reserved. 3// 4// This Source Code Form is subject to the terms of the Mozilla Public 5// License, v. 2.0. If a copy of the MPL was not distributed with this 6// file, You can obtain one at http://mozilla.org/MPL/2.0/. 7// 8 9package compute 10 11import ( 12 "context" 13 "encoding/json" 14 "net/http" 15 "path" 16 "time" 17 18 "github.com/joyent/triton-go/client" 19 "github.com/pkg/errors" 20) 21 22type SnapshotsClient struct { 23 client *client.Client 24} 25 26type Snapshot struct { 27 Name string 28 State string 29 Created time.Time 30 Updated time.Time 31} 32 33type ListSnapshotsInput struct { 34 MachineID string 35} 36 37func (c *SnapshotsClient) List(ctx context.Context, input *ListSnapshotsInput) ([]*Snapshot, error) { 38 fullPath := path.Join("/", c.client.AccountName, "machines", input.MachineID, "snapshots") 39 reqInputs := client.RequestInput{ 40 Method: http.MethodGet, 41 Path: fullPath, 42 } 43 respReader, err := c.client.ExecuteRequest(ctx, reqInputs) 44 if respReader != nil { 45 defer respReader.Close() 46 } 47 if err != nil { 48 return nil, errors.Wrap(err, "unable to list snapshots") 49 } 50 51 var result []*Snapshot 52 decoder := json.NewDecoder(respReader) 53 if err = decoder.Decode(&result); err != nil { 54 return nil, errors.Wrap(err, "unable to decode list snapshots response") 55 } 56 57 return result, nil 58} 59 60type GetSnapshotInput struct { 61 MachineID string 62 Name string 63} 64 65func (c *SnapshotsClient) Get(ctx context.Context, input *GetSnapshotInput) (*Snapshot, error) { 66 fullPath := path.Join("/", c.client.AccountName, "machines", input.MachineID, "snapshots", input.Name) 67 reqInputs := client.RequestInput{ 68 Method: http.MethodGet, 69 Path: fullPath, 70 } 71 respReader, err := c.client.ExecuteRequest(ctx, reqInputs) 72 if respReader != nil { 73 defer respReader.Close() 74 } 75 if err != nil { 76 return nil, errors.Wrap(err, "unable to get snapshot") 77 } 78 79 var result *Snapshot 80 decoder := json.NewDecoder(respReader) 81 if err = decoder.Decode(&result); err != nil { 82 return nil, errors.Wrap(err, "unable to decode get snapshot response") 83 } 84 85 return result, nil 86} 87 88type DeleteSnapshotInput struct { 89 MachineID string 90 Name string 91} 92 93func (c *SnapshotsClient) Delete(ctx context.Context, input *DeleteSnapshotInput) error { 94 fullPath := path.Join("/", c.client.AccountName, "machines", input.MachineID, "snapshots", input.Name) 95 reqInputs := client.RequestInput{ 96 Method: http.MethodDelete, 97 Path: fullPath, 98 } 99 respReader, err := c.client.ExecuteRequest(ctx, reqInputs) 100 if respReader != nil { 101 defer respReader.Close() 102 } 103 if err != nil { 104 return errors.Wrap(err, "unable to delete snapshot") 105 } 106 107 return nil 108} 109 110type StartMachineFromSnapshotInput struct { 111 MachineID string 112 Name string 113} 114 115func (c *SnapshotsClient) StartMachine(ctx context.Context, input *StartMachineFromSnapshotInput) error { 116 fullPath := path.Join("/", c.client.AccountName, "machines", input.MachineID, "snapshots", input.Name) 117 reqInputs := client.RequestInput{ 118 Method: http.MethodPost, 119 Path: fullPath, 120 } 121 respReader, err := c.client.ExecuteRequest(ctx, reqInputs) 122 if respReader != nil { 123 defer respReader.Close() 124 } 125 if err != nil { 126 return errors.Wrap(err, "unable to start machine") 127 } 128 129 return nil 130} 131 132type CreateSnapshotInput struct { 133 MachineID string 134 Name string 135} 136 137func (c *SnapshotsClient) Create(ctx context.Context, input *CreateSnapshotInput) (*Snapshot, error) { 138 fullPath := path.Join("/", c.client.AccountName, "machines", input.MachineID, "snapshots") 139 140 data := make(map[string]interface{}) 141 data["name"] = input.Name 142 143 reqInputs := client.RequestInput{ 144 Method: http.MethodPost, 145 Path: fullPath, 146 Body: data, 147 } 148 149 respReader, err := c.client.ExecuteRequest(ctx, reqInputs) 150 if respReader != nil { 151 defer respReader.Close() 152 } 153 if err != nil { 154 return nil, errors.Wrap(err, "unable to create snapshot") 155 } 156 157 var result *Snapshot 158 decoder := json.NewDecoder(respReader) 159 if err = decoder.Decode(&result); err != nil { 160 return nil, errors.Wrap(err, "unable to decode create snapshot response") 161 } 162 163 return result, nil 164} 165