forked from digitalocean/godo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request digitalocean#108 from digitalocean/feature/snapshots
Add snapshots endpoints.
- Loading branch information
Showing
6 changed files
with
336 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package godo | ||
|
||
import "fmt" | ||
|
||
const snapshotBasePath = "v2/snapshots" | ||
|
||
// SnapshotsService is an interface for interfacing with the snapshots | ||
// endpoints of the DigitalOcean API | ||
// See: https://developers.digitalocean.com/documentation/v2#snapshots | ||
type SnapshotsService interface { | ||
List(*ListOptions) ([]Snapshot, *Response, error) | ||
ListVolume(*ListOptions) ([]Snapshot, *Response, error) | ||
ListDroplet(*ListOptions) ([]Snapshot, *Response, error) | ||
Get(string) (*Snapshot, *Response, error) | ||
Delete(string) (*Response, error) | ||
} | ||
|
||
// SnapshotsServiceOp handles communication with the snapshot related methods of the | ||
// DigitalOcean API. | ||
type SnapshotsServiceOp struct { | ||
client *Client | ||
} | ||
|
||
var _ SnapshotsService = &SnapshotsServiceOp{} | ||
|
||
// Snapshot represents a DigitalOcean Snapshot | ||
type Snapshot struct { | ||
ID string `json:"id,omitempty"` | ||
Name string `json:"name,omitempty"` | ||
ResourceID string `json:"resource_id,omitempty"` | ||
ResourceType string `json:"resource_type,omitempty"` | ||
Regions []string `json:"regions,omitempty"` | ||
MinDiskSize int `json:"min_disk_size,omitempty"` | ||
SizeGigaBytes int `json:"size_gigabytes,omitempty"` | ||
Created string `json:"created_at,omitempty"` | ||
} | ||
|
||
type snapshotRoot struct { | ||
Snapshot *Snapshot `json:"snapshot"` | ||
} | ||
|
||
type snapshotsRoot struct { | ||
Snapshots []Snapshot `json:"snapshots"` | ||
Links *Links `json:"links,omitempty"` | ||
} | ||
|
||
type listSnapshotOptions struct { | ||
ResourceType string `url:"resource_type,omitempty"` | ||
} | ||
|
||
func (s Snapshot) String() string { | ||
return Stringify(s) | ||
} | ||
|
||
// List lists all the snapshots available. | ||
func (s *SnapshotsServiceOp) List(opt *ListOptions) ([]Snapshot, *Response, error) { | ||
return s.list(opt, nil) | ||
} | ||
|
||
// ListDroplet lists all the Droplet snapshots. | ||
func (s *SnapshotsServiceOp) ListDroplet(opt *ListOptions) ([]Snapshot, *Response, error) { | ||
listOpt := listSnapshotOptions{ResourceType: "droplet"} | ||
return s.list(opt, &listOpt) | ||
} | ||
|
||
// ListVolume lists all the volume snapshots. | ||
func (s *SnapshotsServiceOp) ListVolume(opt *ListOptions) ([]Snapshot, *Response, error) { | ||
listOpt := listSnapshotOptions{ResourceType: "volume"} | ||
return s.list(opt, &listOpt) | ||
} | ||
|
||
// GetByID retrieves an snapshot by id. | ||
func (s *SnapshotsServiceOp) Get(snapshotID string) (*Snapshot, *Response, error) { | ||
return s.get(interface{}(snapshotID)) | ||
} | ||
|
||
// Delete an snapshot. | ||
func (s *SnapshotsServiceOp) Delete(snapshotID string) (*Response, error) { | ||
path := fmt.Sprintf("%s/%s", snapshotBasePath, snapshotID) | ||
|
||
req, err := s.client.NewRequest("DELETE", path, nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
resp, err := s.client.Do(req, nil) | ||
|
||
return resp, err | ||
} | ||
|
||
// Helper method for getting an individual snapshot | ||
func (s *SnapshotsServiceOp) get(ID interface{}) (*Snapshot, *Response, error) { | ||
path := fmt.Sprintf("%s/%v", snapshotBasePath, ID) | ||
|
||
req, err := s.client.NewRequest("GET", path, nil) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
root := new(snapshotRoot) | ||
resp, err := s.client.Do(req, root) | ||
if err != nil { | ||
return nil, resp, err | ||
} | ||
|
||
return root.Snapshot, resp, err | ||
} | ||
|
||
// Helper method for listing snapshots | ||
func (s *SnapshotsServiceOp) list(opt *ListOptions, listOpt *listSnapshotOptions) ([]Snapshot, *Response, error) { | ||
path := snapshotBasePath | ||
path, err := addOptions(path, opt) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
path, err = addOptions(path, listOpt) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
req, err := s.client.NewRequest("GET", path, nil) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
root := new(snapshotsRoot) | ||
resp, err := s.client.Do(req, root) | ||
if err != nil { | ||
return nil, resp, err | ||
} | ||
if l := root.Links; l != nil { | ||
resp.Links = l | ||
} | ||
|
||
return root.Snapshots, resp, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
package godo | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
func TestSnapshots_List(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
mux.HandleFunc("/v2/snapshots", func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "GET") | ||
fmt.Fprint(w, `{"snapshots":[{"id":"1"},{"id":"2"}]}`) | ||
}) | ||
|
||
snapshots, _, err := client.Snapshots.List(nil) | ||
if err != nil { | ||
t.Errorf("Snapshots.List returned error: %v", err) | ||
} | ||
|
||
expected := []Snapshot{{ID: "1"}, {ID: "2"}} | ||
if !reflect.DeepEqual(snapshots, expected) { | ||
t.Errorf("Snapshots.List returned %+v, expected %+v", snapshots, expected) | ||
} | ||
} | ||
|
||
func TestSnapshots_ListVolume(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
mux.HandleFunc("/v2/snapshots", func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "GET") | ||
expected := "volume" | ||
actual := r.URL.Query().Get("resource_type") | ||
if actual != expected { | ||
t.Errorf("'type' query = %v, expected %v", actual, expected) | ||
} | ||
fmt.Fprint(w, `{"snapshots":[{"id":"1"},{"id":"2"}]}`) | ||
}) | ||
|
||
snapshots, _, err := client.Snapshots.ListVolume(nil) | ||
if err != nil { | ||
t.Errorf("Snapshots.ListVolume returned error: %v", err) | ||
} | ||
|
||
expected := []Snapshot{{ID: "1"}, {ID: "2"}} | ||
if !reflect.DeepEqual(snapshots, expected) { | ||
t.Errorf("Snapshots.ListVolume returned %+v, expected %+v", snapshots, expected) | ||
} | ||
} | ||
|
||
func TestSnapshots_ListDroplet(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
mux.HandleFunc("/v2/snapshots", func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "GET") | ||
expected := "droplet" | ||
actual := r.URL.Query().Get("resource_type") | ||
if actual != expected { | ||
t.Errorf("'resource_type' query = %v, expected %v", actual, expected) | ||
} | ||
|
||
fmt.Fprint(w, `{"snapshots":[{"id":"1"},{"id":"2"}]}`) | ||
}) | ||
|
||
snapshots, _, err := client.Snapshots.ListDroplet(nil) | ||
if err != nil { | ||
t.Errorf("Snapshots.ListDroplet returned error: %v", err) | ||
} | ||
|
||
expected := []Snapshot{{ID: "1"}, {ID: "2"}} | ||
if !reflect.DeepEqual(snapshots, expected) { | ||
t.Errorf("Snapshots.ListDroplet returned %+v, expected %+v", snapshots, expected) | ||
} | ||
} | ||
|
||
func TestSnapshots_ListSnapshotsMultiplePages(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
mux.HandleFunc("/v2/snapshots", func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "GET") | ||
fmt.Fprint(w, `{"snapshots": [{"id":"1"},{"id":"2"}], "links":{"pages":{"next":"http://example.com/v2/snapshots/?page=2"}}}`) | ||
}) | ||
|
||
_, resp, err := client.Snapshots.List(&ListOptions{Page: 2}) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
checkCurrentPage(t, resp, 1) | ||
} | ||
|
||
func TestSnapshots_RetrievePageByNumber(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
jBlob := ` | ||
{ | ||
"snapshots": [{"id":"1"},{"id":"2"}], | ||
"links":{ | ||
"pages":{ | ||
"next":"http://example.com/v2/snapshots/?page=3", | ||
"prev":"http://example.com/v2/snapshots/?page=1", | ||
"last":"http://example.com/v2/snapshots/?page=3", | ||
"first":"http://example.com/v2/snapshots/?page=1" | ||
} | ||
} | ||
}` | ||
|
||
mux.HandleFunc("/v2/snapshots", func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "GET") | ||
fmt.Fprint(w, jBlob) | ||
}) | ||
|
||
opt := &ListOptions{Page: 2} | ||
_, resp, err := client.Snapshots.List(opt) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
checkCurrentPage(t, resp, 2) | ||
} | ||
|
||
func TestSnapshots_GetSnapshotByID(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
mux.HandleFunc("/v2/snapshots/12345", func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "GET") | ||
fmt.Fprint(w, `{"snapshot":{"id":"12345"}}`) | ||
}) | ||
|
||
snapshots, _, err := client.Snapshots.Get("12345") | ||
if err != nil { | ||
t.Errorf("Snapshot.GetByID returned error: %v", err) | ||
} | ||
|
||
expected := &Snapshot{ID: "12345"} | ||
if !reflect.DeepEqual(snapshots, expected) { | ||
t.Errorf("Snapshots.GetByID returned %+v, expected %+v", snapshots, expected) | ||
} | ||
} | ||
|
||
func TestSnapshots_Destroy(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
mux.HandleFunc("/v2/snapshots/12345", func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "DELETE") | ||
}) | ||
|
||
_, err := client.Snapshots.Delete("12345") | ||
if err != nil { | ||
t.Errorf("Snapshot.Delete returned error: %v", err) | ||
} | ||
} | ||
|
||
func TestSnapshot_String(t *testing.T) { | ||
snapshot := &Snapshot{ | ||
ID: "1", | ||
Name: "Snapsh176ot", | ||
ResourceID: "0", | ||
ResourceType: "droplet", | ||
Regions: []string{"one"}, | ||
MinDiskSize: 20, | ||
SizeGigaBytes: 0, | ||
Created: "2013-11-27T09:24:55Z", | ||
} | ||
|
||
stringified := snapshot.String() | ||
expected := `godo.Snapshot{ID:"1", Name:"Snapsh176ot", ResourceID:"0", ResourceType:"droplet", Regions:["one"], MinDiskSize:20, SizeGigaBytes:0, Created:"2013-11-27T09:24:55Z"}` | ||
if expected != stringified { | ||
t.Errorf("Snapshot.String returned %+v, expected %+v", stringified, expected) | ||
} | ||
} |
Oops, something went wrong.