mirror of https://github.com/docker/docs.git
commit
45d38fd31b
|
@ -123,6 +123,10 @@
|
|||
"ImportPath": "golang.org/x/oauth2",
|
||||
"Rev": "038cb4adce85ed41e285c2e7cc6221a92bfa44aa"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/sys/windows/registry",
|
||||
"Rev": "d9157a9621b69ad1d8d77a1933590c416593f24f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/api/compute/v1",
|
||||
"Rev": "a09229c13c2f13bbdedf7b31b506cad4c83ef3bf"
|
||||
|
@ -138,10 +142,6 @@
|
|||
{
|
||||
"ImportPath": "google.golang.org/cloud/internal",
|
||||
"Rev": "2400193c85c3561d13880d34e0e10c4315bb02af"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/sys",
|
||||
"Rev": "d9157a9621b69ad1d8d77a1933590c416593f24f"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
package backoff
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNextBackOffMillis(t *testing.T) {
|
||||
subtestNextBackOff(t, 0, new(ZeroBackOff))
|
||||
subtestNextBackOff(t, Stop, new(StopBackOff))
|
||||
}
|
||||
|
||||
func subtestNextBackOff(t *testing.T, expectedValue time.Duration, backOffPolicy BackOff) {
|
||||
for i := 0; i < 10; i++ {
|
||||
next := backOffPolicy.NextBackOff()
|
||||
if next != expectedValue {
|
||||
t.Errorf("got: %d expected: %d", next, expectedValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConstantBackOff(t *testing.T) {
|
||||
backoff := NewConstantBackOff(time.Second)
|
||||
if backoff.NextBackOff() != time.Second {
|
||||
t.Error("invalid interval")
|
||||
}
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
package backoff
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestBackOff(t *testing.T) {
|
||||
var (
|
||||
testInitialInterval = 500 * time.Millisecond
|
||||
testRandomizationFactor = 0.1
|
||||
testMultiplier = 2.0
|
||||
testMaxInterval = 5 * time.Second
|
||||
testMaxElapsedTime = 15 * time.Minute
|
||||
)
|
||||
|
||||
exp := NewExponentialBackOff()
|
||||
exp.InitialInterval = testInitialInterval
|
||||
exp.RandomizationFactor = testRandomizationFactor
|
||||
exp.Multiplier = testMultiplier
|
||||
exp.MaxInterval = testMaxInterval
|
||||
exp.MaxElapsedTime = testMaxElapsedTime
|
||||
exp.Reset()
|
||||
|
||||
var expectedResults = []time.Duration{500, 1000, 2000, 4000, 5000, 5000, 5000, 5000, 5000, 5000}
|
||||
for i, d := range expectedResults {
|
||||
expectedResults[i] = d * time.Millisecond
|
||||
}
|
||||
|
||||
for _, expected := range expectedResults {
|
||||
assertEquals(t, expected, exp.currentInterval)
|
||||
// Assert that the next back off falls in the expected range.
|
||||
var minInterval = expected - time.Duration(testRandomizationFactor*float64(expected))
|
||||
var maxInterval = expected + time.Duration(testRandomizationFactor*float64(expected))
|
||||
var actualInterval = exp.NextBackOff()
|
||||
if !(minInterval <= actualInterval && actualInterval <= maxInterval) {
|
||||
t.Error("error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetRandomizedInterval(t *testing.T) {
|
||||
// 33% chance of being 1.
|
||||
assertEquals(t, 1, getRandomValueFromInterval(0.5, 0, 2))
|
||||
assertEquals(t, 1, getRandomValueFromInterval(0.5, 0.33, 2))
|
||||
// 33% chance of being 2.
|
||||
assertEquals(t, 2, getRandomValueFromInterval(0.5, 0.34, 2))
|
||||
assertEquals(t, 2, getRandomValueFromInterval(0.5, 0.66, 2))
|
||||
// 33% chance of being 3.
|
||||
assertEquals(t, 3, getRandomValueFromInterval(0.5, 0.67, 2))
|
||||
assertEquals(t, 3, getRandomValueFromInterval(0.5, 0.99, 2))
|
||||
}
|
||||
|
||||
type TestClock struct {
|
||||
i time.Duration
|
||||
start time.Time
|
||||
}
|
||||
|
||||
func (c *TestClock) Now() time.Time {
|
||||
t := c.start.Add(c.i)
|
||||
c.i += time.Second
|
||||
return t
|
||||
}
|
||||
|
||||
func TestGetElapsedTime(t *testing.T) {
|
||||
var exp = NewExponentialBackOff()
|
||||
exp.Clock = &TestClock{}
|
||||
exp.Reset()
|
||||
|
||||
var elapsedTime = exp.GetElapsedTime()
|
||||
if elapsedTime != time.Second {
|
||||
t.Errorf("elapsedTime=%d", elapsedTime)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaxElapsedTime(t *testing.T) {
|
||||
var exp = NewExponentialBackOff()
|
||||
exp.Clock = &TestClock{start: time.Time{}.Add(10000 * time.Second)}
|
||||
if exp.NextBackOff() != Stop {
|
||||
t.Error("error2")
|
||||
}
|
||||
// Change the currentElapsedTime to be 0 ensuring that the elapsed time will be greater
|
||||
// than the max elapsed time.
|
||||
exp.startTime = time.Time{}
|
||||
assertEquals(t, Stop, exp.NextBackOff())
|
||||
}
|
||||
|
||||
func TestBackOffOverflow(t *testing.T) {
|
||||
var (
|
||||
testInitialInterval time.Duration = math.MaxInt64 / 2
|
||||
testMaxInterval time.Duration = math.MaxInt64
|
||||
testMultiplier float64 = 2.1
|
||||
)
|
||||
|
||||
exp := NewExponentialBackOff()
|
||||
exp.InitialInterval = testInitialInterval
|
||||
exp.Multiplier = testMultiplier
|
||||
exp.MaxInterval = testMaxInterval
|
||||
exp.Reset()
|
||||
|
||||
exp.NextBackOff()
|
||||
// Assert that when an overflow is possible the current varerval time.Duration is set to the max varerval time.Duration .
|
||||
assertEquals(t, testMaxInterval, exp.currentInterval)
|
||||
}
|
||||
|
||||
func assertEquals(t *testing.T, expected, value time.Duration) {
|
||||
if expected != value {
|
||||
t.Errorf("got: %d, expected: %d", value, expected)
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package backoff
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRetry(t *testing.T) {
|
||||
const successOn = 3
|
||||
var i = 0
|
||||
|
||||
// This function is successfull on "successOn" calls.
|
||||
f := func() error {
|
||||
i++
|
||||
log.Printf("function is called %d. time\n", i)
|
||||
|
||||
if i == successOn {
|
||||
log.Println("OK")
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Println("error")
|
||||
return errors.New("error")
|
||||
}
|
||||
|
||||
err := Retry(f, NewExponentialBackOff())
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %s", err.Error())
|
||||
}
|
||||
if i != successOn {
|
||||
t.Errorf("invalid number of retries: %d", i)
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
package backoff
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTicker(t *testing.T) {
|
||||
const successOn = 3
|
||||
var i = 0
|
||||
|
||||
// This function is successfull on "successOn" calls.
|
||||
f := func() error {
|
||||
i++
|
||||
log.Printf("function is called %d. time\n", i)
|
||||
|
||||
if i == successOn {
|
||||
log.Println("OK")
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Println("error")
|
||||
return errors.New("error")
|
||||
}
|
||||
|
||||
b := NewExponentialBackOff()
|
||||
ticker := NewTicker(b)
|
||||
|
||||
var err error
|
||||
for _ = range ticker.C {
|
||||
if err = f(); err != nil {
|
||||
t.Log(err)
|
||||
continue
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %s", err.Error())
|
||||
}
|
||||
if i != successOn {
|
||||
t.Errorf("invalid number of retries: %d", i)
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
package godo
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestActionRequest_String(t *testing.T) {
|
||||
action := &ActionRequest{
|
||||
Type: "transfer",
|
||||
Params: map[string]interface{}{"key-1": "value-1"},
|
||||
}
|
||||
|
||||
stringified := action.String()
|
||||
expected := `godo.ActionRequest{Type:"transfer", Params:map[key-1:value-1]}`
|
||||
if expected != stringified {
|
||||
t.Errorf("Action.Stringify returned %+v, expected %+v", stringified, expected)
|
||||
}
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
package godo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestAction_ActionsServiceOpImplementsActionsService(t *testing.T) {
|
||||
if !Implements((*ActionsService)(nil), new(ActionsServiceOp)) {
|
||||
t.Error("ActionsServiceOp does not implement ActionsService")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAction_List(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/actions", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, `{"actions": [{"id":1},{"id":2}]}`)
|
||||
testMethod(t, r, "GET")
|
||||
})
|
||||
|
||||
actions, _, err := client.Actions.List(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
expected := []Action{{ID: 1}, {ID: 2}}
|
||||
if len(actions) != len(expected) || actions[0].ID != expected[0].ID || actions[1].ID != expected[1].ID {
|
||||
t.Fatalf("unexpected response")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAction_ListActionMultiplePages(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/actions", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, `{"actions": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/droplets/?page=2"}}}`)
|
||||
testMethod(t, r, "GET")
|
||||
})
|
||||
|
||||
_, resp, err := client.Actions.List(nil)
|
||||
if err != nil {
|
||||
t.Fatal(nil)
|
||||
}
|
||||
|
||||
checkCurrentPage(t, resp, 1)
|
||||
}
|
||||
|
||||
func TestAction_RetrievePageByNumber(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
jBlob := `
|
||||
{
|
||||
"actions": [{"id":1},{"id":2}],
|
||||
"links":{
|
||||
"pages":{
|
||||
"next":"http://example.com/v2/actions/?page=3",
|
||||
"prev":"http://example.com/v2/actions/?page=1",
|
||||
"last":"http://example.com/v2/actions/?page=3",
|
||||
"first":"http://example.com/v2/actions/?page=1"
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
mux.HandleFunc("/v2/actions", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, jBlob)
|
||||
})
|
||||
|
||||
opt := &ListOptions{Page: 2}
|
||||
_, resp, err := client.Actions.List(opt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
checkCurrentPage(t, resp, 2)
|
||||
}
|
||||
|
||||
func TestAction_Get(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/actions/12345", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, `{"action": {"id":12345}}`)
|
||||
testMethod(t, r, "GET")
|
||||
})
|
||||
|
||||
action, _, err := client.Actions.Get(12345)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if action.ID != 12345 {
|
||||
t.Fatalf("unexpected response")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAction_String(t *testing.T) {
|
||||
pt, err := time.Parse(time.RFC3339, "2014-05-08T20:36:47Z")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
startedAt := &Timestamp{
|
||||
Time: pt,
|
||||
}
|
||||
action := &Action{
|
||||
ID: 1,
|
||||
Status: "in-progress",
|
||||
Type: "transfer",
|
||||
StartedAt: startedAt,
|
||||
}
|
||||
|
||||
stringified := action.String()
|
||||
expected := `godo.Action{ID:1, Status:"in-progress", Type:"transfer", ` +
|
||||
`StartedAt:godo.Timestamp{2014-05-08 20:36:47 +0000 UTC}, ` +
|
||||
`ResourceID:0, ResourceType:""}`
|
||||
if expected != stringified {
|
||||
t.Errorf("Action.Stringify returned %+v, expected %+v", stringified, expected)
|
||||
}
|
||||
}
|
|
@ -1,345 +0,0 @@
|
|||
package godo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAction_DomainsServiceOpImplementsDomainsService(t *testing.T) {
|
||||
if !Implements((*DomainsService)(nil), new(DomainsServiceOp)) {
|
||||
t.Error("DomainsServiceOp does not implement DomainsService")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDomains_ListDomains(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/domains", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"domains": [{"name":"foo.com"},{"name":"bar.com"}]}`)
|
||||
})
|
||||
|
||||
domains, _, err := client.Domains.List(nil)
|
||||
if err != nil {
|
||||
t.Errorf("Domains.List returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := []Domain{{Name: "foo.com"}, {Name: "bar.com"}}
|
||||
if !reflect.DeepEqual(domains, expected) {
|
||||
t.Errorf("Domains.List returned %+v, expected %+v", domains, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDomains_ListDomainsMultiplePages(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/domains", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"domains": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/domains/?page=2"}}}`)
|
||||
})
|
||||
|
||||
_, resp, err := client.Domains.List(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
checkCurrentPage(t, resp, 1)
|
||||
}
|
||||
|
||||
func TestDomains_RetrievePageByNumber(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
jBlob := `
|
||||
{
|
||||
"domains": [{"id":1},{"id":2}],
|
||||
"links":{
|
||||
"pages":{
|
||||
"next":"http://example.com/v2/domains/?page=3",
|
||||
"prev":"http://example.com/v2/domains/?page=1",
|
||||
"last":"http://example.com/v2/domains/?page=3",
|
||||
"first":"http://example.com/v2/domains/?page=1"
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
mux.HandleFunc("/v2/domains", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, jBlob)
|
||||
})
|
||||
|
||||
opt := &ListOptions{Page: 2}
|
||||
_, resp, err := client.Domains.List(opt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
checkCurrentPage(t, resp, 2)
|
||||
}
|
||||
|
||||
func TestDomains_GetDomain(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/domains/example.com", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"domain":{"name":"example.com"}}`)
|
||||
})
|
||||
|
||||
domains, _, err := client.Domains.Get("example.com")
|
||||
if err != nil {
|
||||
t.Errorf("domain.Get returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &DomainRoot{Domain: &Domain{Name: "example.com"}}
|
||||
if !reflect.DeepEqual(domains, expected) {
|
||||
t.Errorf("domains.Get returned %+v, expected %+v", domains, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDomains_Create(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
createRequest := &DomainCreateRequest{
|
||||
Name: "example.com",
|
||||
IPAddress: "127.0.0.1",
|
||||
}
|
||||
|
||||
mux.HandleFunc("/v2/domains", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(DomainCreateRequest)
|
||||
err := json.NewDecoder(r.Body).Decode(v)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testMethod(t, r, "POST")
|
||||
if !reflect.DeepEqual(v, createRequest) {
|
||||
t.Errorf("Request body = %+v, expected %+v", v, createRequest)
|
||||
}
|
||||
|
||||
dr := DomainRoot{&Domain{Name: v.Name}}
|
||||
b, err := json.Marshal(dr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Fprint(w, string(b))
|
||||
})
|
||||
|
||||
domain, _, err := client.Domains.Create(createRequest)
|
||||
if err != nil {
|
||||
t.Errorf("Domains.Create returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &DomainRoot{Domain: &Domain{Name: "example.com"}}
|
||||
if !reflect.DeepEqual(domain, expected) {
|
||||
t.Errorf("Domains.Create returned %+v, expected %+v", domain, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDomains_Destroy(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/domains/example.com", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "DELETE")
|
||||
})
|
||||
|
||||
_, err := client.Domains.Delete("example.com")
|
||||
if err != nil {
|
||||
t.Errorf("Domains.Delete returned error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDomains_AllRecordsForDomainName(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/domains/example.com/records", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"domain_records":[{"id":1},{"id":2}]}`)
|
||||
})
|
||||
|
||||
records, _, err := client.Domains.Records("example.com", nil)
|
||||
if err != nil {
|
||||
t.Errorf("Domains.List returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := []DomainRecord{{ID: 1}, {ID: 2}}
|
||||
if !reflect.DeepEqual(records, expected) {
|
||||
t.Errorf("Domains.List returned %+v, expected %+v", records, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDomains_AllRecordsForDomainName_PerPage(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/domains/example.com/records", func(w http.ResponseWriter, r *http.Request) {
|
||||
perPage := r.URL.Query().Get("per_page")
|
||||
if perPage != "2" {
|
||||
t.Fatalf("expected '2', got '%s'", perPage)
|
||||
}
|
||||
|
||||
fmt.Fprint(w, `{"domain_records":[{"id":1},{"id":2}]}`)
|
||||
})
|
||||
|
||||
dro := &ListOptions{PerPage: 2}
|
||||
records, _, err := client.Domains.Records("example.com", dro)
|
||||
if err != nil {
|
||||
t.Errorf("Domains.List returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := []DomainRecord{{ID: 1}, {ID: 2}}
|
||||
if !reflect.DeepEqual(records, expected) {
|
||||
t.Errorf("Domains.List returned %+v, expected %+v", records, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDomains_GetRecordforDomainName(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/domains/example.com/records/1", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"domain_record":{"id":1}}`)
|
||||
})
|
||||
|
||||
record, _, err := client.Domains.Record("example.com", 1)
|
||||
if err != nil {
|
||||
t.Errorf("Domains.GetRecord returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &DomainRecord{ID: 1}
|
||||
if !reflect.DeepEqual(record, expected) {
|
||||
t.Errorf("Domains.GetRecord returned %+v, expected %+v", record, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDomains_DeleteRecordForDomainName(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/domains/example.com/records/1", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "DELETE")
|
||||
})
|
||||
|
||||
_, err := client.Domains.DeleteRecord("example.com", 1)
|
||||
if err != nil {
|
||||
t.Errorf("Domains.RecordDelete returned error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDomains_CreateRecordForDomainName(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
createRequest := &DomainRecordEditRequest{
|
||||
Type: "CNAME",
|
||||
Name: "example",
|
||||
Data: "@",
|
||||
Priority: 10,
|
||||
Port: 10,
|
||||
Weight: 10,
|
||||
}
|
||||
|
||||
mux.HandleFunc("/v2/domains/example.com/records",
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(DomainRecordEditRequest)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "POST")
|
||||
if !reflect.DeepEqual(v, createRequest) {
|
||||
t.Errorf("Request body = %+v, expected %+v", v, createRequest)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `{"domain_record": {"id":1}}`)
|
||||
})
|
||||
|
||||
record, _, err := client.Domains.CreateRecord("example.com", createRequest)
|
||||
if err != nil {
|
||||
t.Errorf("Domains.CreateRecord returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &DomainRecord{ID: 1}
|
||||
if !reflect.DeepEqual(record, expected) {
|
||||
t.Errorf("Domains.CreateRecord returned %+v, expected %+v", record, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDomains_EditRecordForDomainName(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
editRequest := &DomainRecordEditRequest{
|
||||
Type: "CNAME",
|
||||
Name: "example",
|
||||
Data: "@",
|
||||
Priority: 10,
|
||||
Port: 10,
|
||||
Weight: 10,
|
||||
}
|
||||
|
||||
mux.HandleFunc("/v2/domains/example.com/records/1", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(DomainRecordEditRequest)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "PUT")
|
||||
if !reflect.DeepEqual(v, editRequest) {
|
||||
t.Errorf("Request body = %+v, expected %+v", v, editRequest)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `{"id":1}`)
|
||||
})
|
||||
|
||||
record, _, err := client.Domains.EditRecord("example.com", 1, editRequest)
|
||||
if err != nil {
|
||||
t.Errorf("Domains.EditRecord returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &DomainRecord{ID: 1}
|
||||
if !reflect.DeepEqual(record, expected) {
|
||||
t.Errorf("Domains.EditRecord returned %+v, expected %+v", record, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDomainRecord_String(t *testing.T) {
|
||||
record := &DomainRecord{
|
||||
ID: 1,
|
||||
Type: "CNAME",
|
||||
Name: "example",
|
||||
Data: "@",
|
||||
Priority: 10,
|
||||
Port: 10,
|
||||
Weight: 10,
|
||||
}
|
||||
|
||||
stringified := record.String()
|
||||
expected := `godo.DomainRecord{ID:1, Type:"CNAME", Name:"example", Data:"@", Priority:10, Port:10, Weight:10}`
|
||||
if expected != stringified {
|
||||
t.Errorf("DomainRecord.String returned %+v, expected %+v", stringified, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDomainRecordEditRequest_String(t *testing.T) {
|
||||
record := &DomainRecordEditRequest{
|
||||
Type: "CNAME",
|
||||
Name: "example",
|
||||
Data: "@",
|
||||
Priority: 10,
|
||||
Port: 10,
|
||||
Weight: 10,
|
||||
}
|
||||
|
||||
stringified := record.String()
|
||||
expected := `godo.DomainRecordEditRequest{Type:"CNAME", Name:"example", Data:"@", Priority:10, Port:10, Weight:10}`
|
||||
if expected != stringified {
|
||||
t.Errorf("DomainRecordEditRequest.String returned %+v, expected %+v", stringified, expected)
|
||||
}
|
||||
}
|
|
@ -1,305 +0,0 @@
|
|||
package godo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDropletActions_DropletActionsServiceOpImplementsDropletActionsService(t *testing.T) {
|
||||
if !Implements((*DropletActionsService)(nil), new(DropletActionsServiceOp)) {
|
||||
t.Error("DropletActionsServiceOp does not implement DropletActionsService")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropletActions_Shutdown(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
request := &ActionRequest{
|
||||
Type: "shutdown",
|
||||
}
|
||||
|
||||
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(ActionRequest)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "POST")
|
||||
if !reflect.DeepEqual(v, request) {
|
||||
t.Errorf("Request body = %+v, expected %+v", v, request)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
|
||||
})
|
||||
|
||||
action, _, err := client.DropletActions.Shutdown(1)
|
||||
if err != nil {
|
||||
t.Errorf("DropletActions.Shutdown returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &Action{Status: "in-progress"}
|
||||
if !reflect.DeepEqual(action, expected) {
|
||||
t.Errorf("DropletActions.Shutdown returned %+v, expected %+v", action, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropletAction_PowerOff(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
request := &ActionRequest{
|
||||
Type: "power_off",
|
||||
}
|
||||
|
||||
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(ActionRequest)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "POST")
|
||||
if !reflect.DeepEqual(v, request) {
|
||||
t.Errorf("Request body = %+v, expected %+v", v, request)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
|
||||
})
|
||||
|
||||
action, _, err := client.DropletActions.PowerOff(1)
|
||||
if err != nil {
|
||||
t.Errorf("DropletActions.Shutdown returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &Action{Status: "in-progress"}
|
||||
if !reflect.DeepEqual(action, expected) {
|
||||
t.Errorf("DropletActions.Shutdown returned %+v, expected %+v", action, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropletAction_PowerOn(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
request := &ActionRequest{
|
||||
Type: "power_on",
|
||||
}
|
||||
|
||||
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(ActionRequest)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "POST")
|
||||
if !reflect.DeepEqual(v, request) {
|
||||
t.Errorf("Request body = %+v, expected %+v", v, request)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
|
||||
})
|
||||
|
||||
action, _, err := client.DropletActions.PowerOn(1)
|
||||
if err != nil {
|
||||
t.Errorf("DropletActions.PowerOn returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &Action{Status: "in-progress"}
|
||||
if !reflect.DeepEqual(action, expected) {
|
||||
t.Errorf("DropletActions.PowerOn returned %+v, expected %+v", action, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropletAction_Reboot(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
request := &ActionRequest{
|
||||
Type: "reboot",
|
||||
}
|
||||
|
||||
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(ActionRequest)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "POST")
|
||||
if !reflect.DeepEqual(v, request) {
|
||||
t.Errorf("Request body = %+v, expected %+v", v, request)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
|
||||
|
||||
})
|
||||
|
||||
action, _, err := client.DropletActions.Reboot(1)
|
||||
if err != nil {
|
||||
t.Errorf("DropletActions.Shutdown returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &Action{Status: "in-progress"}
|
||||
if !reflect.DeepEqual(action, expected) {
|
||||
t.Errorf("DropletActions.Shutdown returned %+v, expected %+v", action, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropletAction_Restore(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
options := map[string]interface{}{
|
||||
"image": float64(1),
|
||||
}
|
||||
|
||||
request := &ActionRequest{
|
||||
Type: "restore",
|
||||
Params: options,
|
||||
}
|
||||
|
||||
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(ActionRequest)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "POST")
|
||||
|
||||
if !reflect.DeepEqual(v, request) {
|
||||
t.Errorf("Request body = %+v, expected %+v", v, request)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
|
||||
|
||||
})
|
||||
|
||||
action, _, err := client.DropletActions.Restore(1, 1)
|
||||
if err != nil {
|
||||
t.Errorf("DropletActions.Shutdown returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &Action{Status: "in-progress"}
|
||||
if !reflect.DeepEqual(action, expected) {
|
||||
t.Errorf("DropletActions.Shutdown returned %+v, expected %+v", action, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropletAction_Resize(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
options := map[string]interface{}{
|
||||
"size": "1024mb",
|
||||
}
|
||||
|
||||
request := &ActionRequest{
|
||||
Type: "resize",
|
||||
Params: options,
|
||||
}
|
||||
|
||||
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(ActionRequest)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "POST")
|
||||
|
||||
if !reflect.DeepEqual(v, request) {
|
||||
t.Errorf("Request body = %+v, expected %+v", v, request)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
|
||||
|
||||
})
|
||||
|
||||
action, _, err := client.DropletActions.Resize(1, "1024mb")
|
||||
if err != nil {
|
||||
t.Errorf("DropletActions.Shutdown returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &Action{Status: "in-progress"}
|
||||
if !reflect.DeepEqual(action, expected) {
|
||||
t.Errorf("DropletActions.Shutdown returned %+v, expected %+v", action, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropletAction_Rename(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
options := map[string]interface{}{
|
||||
"name": "Droplet-Name",
|
||||
}
|
||||
|
||||
request := &ActionRequest{
|
||||
Type: "rename",
|
||||
Params: options,
|
||||
}
|
||||
|
||||
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(ActionRequest)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "POST")
|
||||
|
||||
if !reflect.DeepEqual(v, request) {
|
||||
t.Errorf("Request body = %+v, expected %+v", v, request)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
|
||||
})
|
||||
|
||||
action, _, err := client.DropletActions.Rename(1, "Droplet-Name")
|
||||
if err != nil {
|
||||
t.Errorf("DropletActions.Shutdown returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &Action{Status: "in-progress"}
|
||||
if !reflect.DeepEqual(action, expected) {
|
||||
t.Errorf("DropletActions.Shutdown returned %+v, expected %+v", action, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropletAction_PowerCycle(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
request := &ActionRequest{
|
||||
Type: "power_cycle",
|
||||
}
|
||||
|
||||
mux.HandleFunc("/v2/droplets/1/actions", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(ActionRequest)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "POST")
|
||||
if !reflect.DeepEqual(v, request) {
|
||||
t.Errorf("Request body = %+v, expected %+v", v, request)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
|
||||
|
||||
})
|
||||
|
||||
action, _, err := client.DropletActions.PowerCycle(1)
|
||||
if err != nil {
|
||||
t.Errorf("DropletActions.Shutdown returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &Action{Status: "in-progress"}
|
||||
if !reflect.DeepEqual(action, expected) {
|
||||
t.Errorf("DropletActions.Shutdown returned %+v, expected %+v", action, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropletActions_Get(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/droplets/123/actions/456", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
|
||||
})
|
||||
|
||||
action, _, err := client.DropletActions.Get(123, 456)
|
||||
if err != nil {
|
||||
t.Errorf("DropletActions.Get returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &Action{Status: "in-progress"}
|
||||
if !reflect.DeepEqual(action, expected) {
|
||||
t.Errorf("DropletActions.Get returned %+v, expected %+v", action, expected)
|
||||
}
|
||||
}
|
|
@ -1,242 +0,0 @@
|
|||
package godo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAction_DropletsServiceOpImplementsActionService(t *testing.T) {
|
||||
if !Implements((*DropletsService)(nil), new(DropletsServiceOp)) {
|
||||
t.Error("DropletsServiceOp does not implement DropletsService")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDroplets_ListDroplets(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"droplets": [{"id":1},{"id":2}]}`)
|
||||
})
|
||||
|
||||
droplets, _, err := client.Droplets.List(nil)
|
||||
if err != nil {
|
||||
t.Errorf("Droplets.List returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := []Droplet{{ID: 1}, {ID: 2}}
|
||||
if !reflect.DeepEqual(droplets, expected) {
|
||||
t.Errorf("Droplets.List returned %+v, expected %+v", droplets, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDroplets_ListDropletsMultiplePages(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
|
||||
dr := dropletsRoot{
|
||||
Droplets: []Droplet{
|
||||
Droplet{ID: 1},
|
||||
Droplet{ID: 2},
|
||||
},
|
||||
Links: &Links{
|
||||
Pages: &Pages{Next: "http://example.com/v2/droplets/?page=2"},
|
||||
},
|
||||
}
|
||||
|
||||
b, err := json.Marshal(dr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Fprint(w, string(b))
|
||||
})
|
||||
|
||||
_, resp, err := client.Droplets.List(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
checkCurrentPage(t, resp, 1)
|
||||
}
|
||||
|
||||
func TestDroplets_RetrievePageByNumber(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
jBlob := `
|
||||
{
|
||||
"droplets": [{"id":1},{"id":2}],
|
||||
"links":{
|
||||
"pages":{
|
||||
"next":"http://example.com/v2/droplets/?page=3",
|
||||
"prev":"http://example.com/v2/droplets/?page=1",
|
||||
"last":"http://example.com/v2/droplets/?page=3",
|
||||
"first":"http://example.com/v2/droplets/?page=1"
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, jBlob)
|
||||
})
|
||||
|
||||
opt := &ListOptions{Page: 2}
|
||||
_, resp, err := client.Droplets.List(opt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
checkCurrentPage(t, resp, 2)
|
||||
}
|
||||
|
||||
func TestDroplets_GetDroplet(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/droplets/12345", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"droplet":{"id":12345}}`)
|
||||
})
|
||||
|
||||
droplets, _, err := client.Droplets.Get(12345)
|
||||
if err != nil {
|
||||
t.Errorf("Droplet.Get returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &DropletRoot{Droplet: &Droplet{ID: 12345}}
|
||||
if !reflect.DeepEqual(droplets, expected) {
|
||||
t.Errorf("Droplets.Get returned %+v, expected %+v", droplets, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDroplets_Create(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
createRequest := &DropletCreateRequest{
|
||||
Name: "name",
|
||||
Region: "region",
|
||||
Size: "size",
|
||||
Image: "1",
|
||||
}
|
||||
|
||||
mux.HandleFunc("/v2/droplets", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(DropletCreateRequest)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "POST")
|
||||
if !reflect.DeepEqual(v, createRequest) {
|
||||
t.Errorf("Request body = %+v, expected %+v", v, createRequest)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `{"droplet":{"id":1}, "links":{"actions": [{"id": 1, "href": "http://example.com", "rel": "create"}]}}`)
|
||||
})
|
||||
|
||||
root, resp, err := client.Droplets.Create(createRequest)
|
||||
if err != nil {
|
||||
t.Errorf("Droplets.Create returned error: %v", err)
|
||||
}
|
||||
|
||||
if id := root.Droplet.ID; id != 1 {
|
||||
t.Errorf("expected id '%d', received '%d'", 1, id)
|
||||
}
|
||||
|
||||
if a := resp.Links.Actions[0]; a.ID != 1 {
|
||||
t.Errorf("expected action id '%d', received '%d'", 1, a.ID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDroplets_Destroy(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/droplets/12345", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "DELETE")
|
||||
})
|
||||
|
||||
_, err := client.Droplets.Delete(12345)
|
||||
if err != nil {
|
||||
t.Errorf("Droplet.Delete returned error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetwork_String(t *testing.T) {
|
||||
network := &Network{
|
||||
IPAddress: "192.168.1.2",
|
||||
Netmask: "255.255.255.0",
|
||||
Gateway: "192.168.1.1",
|
||||
}
|
||||
|
||||
stringified := network.String()
|
||||
expected := `godo.Network{IPAddress:"192.168.1.2", Netmask:"255.255.255.0", Gateway:"192.168.1.1", Type:""}`
|
||||
if expected != stringified {
|
||||
t.Errorf("Distribution.String returned %+v, expected %+v", stringified, expected)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestDroplet_String(t *testing.T) {
|
||||
|
||||
region := &Region{
|
||||
Slug: "region",
|
||||
Name: "Region",
|
||||
Sizes: []string{"1", "2"},
|
||||
Available: true,
|
||||
}
|
||||
|
||||
image := &Image{
|
||||
ID: 1,
|
||||
Name: "Image",
|
||||
Distribution: "Ubuntu",
|
||||
Slug: "image",
|
||||
Public: true,
|
||||
Regions: []string{"one", "two"},
|
||||
}
|
||||
|
||||
size := &Size{
|
||||
Slug: "size",
|
||||
PriceMonthly: 123,
|
||||
PriceHourly: 456,
|
||||
Regions: []string{"1", "2"},
|
||||
}
|
||||
network := &Network{
|
||||
IPAddress: "192.168.1.2",
|
||||
Netmask: "255.255.255.0",
|
||||
Gateway: "192.168.1.1",
|
||||
}
|
||||
networks := &Networks{
|
||||
V4: []Network{*network},
|
||||
}
|
||||
|
||||
droplet := &Droplet{
|
||||
ID: 1,
|
||||
Name: "droplet",
|
||||
Memory: 123,
|
||||
Vcpus: 456,
|
||||
Disk: 789,
|
||||
Region: region,
|
||||
Image: image,
|
||||
Size: size,
|
||||
BackupIDs: []int{1},
|
||||
SnapshotIDs: []int{1},
|
||||
ActionIDs: []int{1},
|
||||
Locked: false,
|
||||
Status: "active",
|
||||
Networks: networks,
|
||||
}
|
||||
|
||||
stringified := droplet.String()
|
||||
expected := `godo.Droplet{ID:1, Name:"droplet", Memory:123, Vcpus:456, Disk:789, Region:godo.Region{Slug:"region", Name:"Region", Sizes:["1" "2"], Available:true}, Image:godo.Image{ID:1, Name:"Image", Distribution:"Ubuntu", Slug:"image", Public:true, Regions:["one" "two"]}, Size:godo.Size{Slug:"size", Memory:0, Vcpus:0, Disk:0, PriceMonthly:123, PriceHourly:456, Regions:["1" "2"]}, BackupIDs:[1], SnapshotIDs:[1], Locked:false, Status:"active", Networks:godo.Networks{V4:[godo.Network{IPAddress:"192.168.1.2", Netmask:"255.255.255.0", Gateway:"192.168.1.1", Type:""}]}, ActionIDs:[1]}`
|
||||
if expected != stringified {
|
||||
t.Errorf("Droplet.String returned %+v, expected %+v", stringified, expected)
|
||||
}
|
||||
}
|
|
@ -1,325 +0,0 @@
|
|||
package godo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
mux *http.ServeMux
|
||||
|
||||
client *Client
|
||||
|
||||
server *httptest.Server
|
||||
)
|
||||
|
||||
func setup() {
|
||||
mux = http.NewServeMux()
|
||||
server = httptest.NewServer(mux)
|
||||
|
||||
client = NewClient(nil)
|
||||
url, _ := url.Parse(server.URL)
|
||||
client.BaseURL = url
|
||||
}
|
||||
|
||||
func teardown() {
|
||||
server.Close()
|
||||
}
|
||||
|
||||
func testMethod(t *testing.T, r *http.Request, expected string) {
|
||||
if expected != r.Method {
|
||||
t.Errorf("Request method = %v, expected %v", r.Method, expected)
|
||||
}
|
||||
}
|
||||
|
||||
type values map[string]string
|
||||
|
||||
func testFormValues(t *testing.T, r *http.Request, values values) {
|
||||
expected := url.Values{}
|
||||
for k, v := range values {
|
||||
expected.Add(k, v)
|
||||
}
|
||||
|
||||
r.ParseForm()
|
||||
if !reflect.DeepEqual(expected, r.Form) {
|
||||
t.Errorf("Request parameters = %v, expected %v", r.Form, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func testURLParseError(t *testing.T, err error) {
|
||||
if err == nil {
|
||||
t.Errorf("Expected error to be returned")
|
||||
}
|
||||
if err, ok := err.(*url.Error); !ok || err.Op != "parse" {
|
||||
t.Errorf("Expected URL parse error, got %+v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewClient(t *testing.T) {
|
||||
c := NewClient(nil)
|
||||
if c.BaseURL.String() != defaultBaseURL {
|
||||
t.Errorf("NewClient BaseURL = %v, expected %v", c.BaseURL.String(), defaultBaseURL)
|
||||
}
|
||||
|
||||
if c.UserAgent != userAgent {
|
||||
t.Errorf("NewClick UserAgent = %v, expected %v", c.UserAgent, userAgent)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewRequest(t *testing.T) {
|
||||
c := NewClient(nil)
|
||||
|
||||
inURL, outURL := "/foo", defaultBaseURL+"foo"
|
||||
inBody, outBody := &DropletCreateRequest{Name: "l"},
|
||||
`{"name":"l","region":"","size":"","image":"",`+
|
||||
`"ssh_keys":null,"backups":false,"ipv6":false,`+
|
||||
`"private_networking":false,"user_data":""}`+"\n"
|
||||
req, _ := c.NewRequest("GET", inURL, inBody)
|
||||
|
||||
// test relative URL was expanded
|
||||
if req.URL.String() != outURL {
|
||||
t.Errorf("NewRequest(%v) URL = %v, expected %v", inURL, req.URL, outURL)
|
||||
}
|
||||
|
||||
// test body was JSON encoded
|
||||
body, _ := ioutil.ReadAll(req.Body)
|
||||
if string(body) != outBody {
|
||||
t.Errorf("NewRequest(%v)Body = %v, expected %v", inBody, string(body), outBody)
|
||||
}
|
||||
|
||||
// test default user-agent is attached to the request
|
||||
userAgent := req.Header.Get("User-Agent")
|
||||
if c.UserAgent != userAgent {
|
||||
t.Errorf("NewRequest() User-Agent = %v, expected %v", userAgent, c.UserAgent)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewRequest_invalidJSON(t *testing.T) {
|
||||
c := NewClient(nil)
|
||||
|
||||
type T struct {
|
||||
A map[int]interface{}
|
||||
}
|
||||
_, err := c.NewRequest("GET", "/", &T{})
|
||||
|
||||
if err == nil {
|
||||
t.Error("Expected error to be returned.")
|
||||
}
|
||||
if err, ok := err.(*json.UnsupportedTypeError); !ok {
|
||||
t.Errorf("Expected a JSON error; got %#v.", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewRequest_badURL(t *testing.T) {
|
||||
c := NewClient(nil)
|
||||
_, err := c.NewRequest("GET", ":", nil)
|
||||
testURLParseError(t, err)
|
||||
}
|
||||
|
||||
func TestDo(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
type foo struct {
|
||||
A string
|
||||
}
|
||||
|
||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
if m := "GET"; m != r.Method {
|
||||
t.Errorf("Request method = %v, expected %v", r.Method, m)
|
||||
}
|
||||
fmt.Fprint(w, `{"A":"a"}`)
|
||||
})
|
||||
|
||||
req, _ := client.NewRequest("GET", "/", nil)
|
||||
body := new(foo)
|
||||
client.Do(req, body)
|
||||
|
||||
expected := &foo{"a"}
|
||||
if !reflect.DeepEqual(body, expected) {
|
||||
t.Errorf("Response body = %v, expected %v", body, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDo_httpError(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Bad Request", 400)
|
||||
})
|
||||
|
||||
req, _ := client.NewRequest("GET", "/", nil)
|
||||
_, err := client.Do(req, nil)
|
||||
|
||||
if err == nil {
|
||||
t.Error("Expected HTTP 400 error.")
|
||||
}
|
||||
}
|
||||
|
||||
// Test handling of an error caused by the internal http client's Do()
|
||||
// function.
|
||||
func TestDo_redirectLoop(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, "/", http.StatusFound)
|
||||
})
|
||||
|
||||
req, _ := client.NewRequest("GET", "/", nil)
|
||||
_, err := client.Do(req, nil)
|
||||
|
||||
if err == nil {
|
||||
t.Error("Expected error to be returned.")
|
||||
}
|
||||
if err, ok := err.(*url.Error); !ok {
|
||||
t.Errorf("Expected a URL error; got %#v.", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckResponse(t *testing.T) {
|
||||
res := &http.Response{
|
||||
Request: &http.Request{},
|
||||
StatusCode: http.StatusBadRequest,
|
||||
Body: ioutil.NopCloser(strings.NewReader(`{"message":"m",
|
||||
"errors": [{"resource": "r", "field": "f", "code": "c"}]}`)),
|
||||
}
|
||||
err := CheckResponse(res).(*ErrorResponse)
|
||||
|
||||
if err == nil {
|
||||
t.Fatalf("Expected error response.")
|
||||
}
|
||||
|
||||
expected := &ErrorResponse{
|
||||
Response: res,
|
||||
Message: "m",
|
||||
}
|
||||
if !reflect.DeepEqual(err, expected) {
|
||||
t.Errorf("Error = %#v, expected %#v", err, expected)
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that we properly handle API errors that do not contain a response
|
||||
// body
|
||||
func TestCheckResponse_noBody(t *testing.T) {
|
||||
res := &http.Response{
|
||||
Request: &http.Request{},
|
||||
StatusCode: http.StatusBadRequest,
|
||||
Body: ioutil.NopCloser(strings.NewReader("")),
|
||||
}
|
||||
err := CheckResponse(res).(*ErrorResponse)
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("Expected error response.")
|
||||
}
|
||||
|
||||
expected := &ErrorResponse{
|
||||
Response: res,
|
||||
}
|
||||
if !reflect.DeepEqual(err, expected) {
|
||||
t.Errorf("Error = %#v, expected %#v", err, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorResponse_Error(t *testing.T) {
|
||||
res := &http.Response{Request: &http.Request{}}
|
||||
err := ErrorResponse{Message: "m", Response: res}
|
||||
if err.Error() == "" {
|
||||
t.Errorf("Expected non-empty ErrorResponse.Error()")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDo_rateLimit(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Add(headerRateLimit, "60")
|
||||
w.Header().Add(headerRateRemaining, "59")
|
||||
w.Header().Add(headerRateReset, "1372700873")
|
||||
})
|
||||
|
||||
var expected int
|
||||
|
||||
if expected = 0; client.Rate.Limit != expected {
|
||||
t.Errorf("Client rate limit = %v, expected %v", client.Rate.Limit, expected)
|
||||
}
|
||||
if expected = 0; client.Rate.Remaining != expected {
|
||||
t.Errorf("Client rate remaining = %v, got %v", client.Rate.Remaining, expected)
|
||||
}
|
||||
if !client.Rate.Reset.IsZero() {
|
||||
t.Errorf("Client rate reset not initialized to zero value")
|
||||
}
|
||||
|
||||
req, _ := client.NewRequest("GET", "/", nil)
|
||||
client.Do(req, nil)
|
||||
|
||||
if expected = 60; client.Rate.Limit != expected {
|
||||
t.Errorf("Client rate limit = %v, expected %v", client.Rate.Limit, expected)
|
||||
}
|
||||
if expected = 59; client.Rate.Remaining != expected {
|
||||
t.Errorf("Client rate remaining = %v, expected %v", client.Rate.Remaining, expected)
|
||||
}
|
||||
reset := time.Date(2013, 7, 1, 17, 47, 53, 0, time.UTC)
|
||||
if client.Rate.Reset.UTC() != reset {
|
||||
t.Errorf("Client rate reset = %v, expected %v", client.Rate.Reset, reset)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDo_rateLimit_errorResponse(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Add(headerRateLimit, "60")
|
||||
w.Header().Add(headerRateRemaining, "59")
|
||||
w.Header().Add(headerRateReset, "1372700873")
|
||||
http.Error(w, "Bad Request", 400)
|
||||
})
|
||||
|
||||
var expected int
|
||||
|
||||
req, _ := client.NewRequest("GET", "/", nil)
|
||||
client.Do(req, nil)
|
||||
|
||||
if expected = 60; client.Rate.Limit != expected {
|
||||
t.Errorf("Client rate limit = %v, expected %v", client.Rate.Limit, expected)
|
||||
}
|
||||
if expected = 59; client.Rate.Remaining != expected {
|
||||
t.Errorf("Client rate remaining = %v, expected %v", client.Rate.Remaining, expected)
|
||||
}
|
||||
reset := time.Date(2013, 7, 1, 17, 47, 53, 0, time.UTC)
|
||||
if client.Rate.Reset.UTC() != reset {
|
||||
t.Errorf("Client rate reset = %v, expected %v", client.Rate.Reset, reset)
|
||||
}
|
||||
}
|
||||
|
||||
func Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
interfaceType := reflect.TypeOf(interfaceObject).Elem()
|
||||
if !reflect.TypeOf(object).Implements(interfaceType) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func checkCurrentPage(t *testing.T, resp *Response, expectedPage int) {
|
||||
links := resp.Links
|
||||
p, err := links.CurrentPage()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if p != expectedPage {
|
||||
t.Fatalf("expected current page to be '%d', was '%d'", expectedPage, p)
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
package godo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestImageActions_ImageActionsServiceOpImplementsImageActionsService(t *testing.T) {
|
||||
if !Implements((*ImageActionsService)(nil), new(ImageActionsServiceOp)) {
|
||||
t.Error("ImageActionsServiceOp does not implement ImageActionsService")
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageActions_Transfer(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
transferRequest := &ActionRequest{}
|
||||
|
||||
mux.HandleFunc("/v2/images/12345/actions", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(ActionRequest)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "POST")
|
||||
if !reflect.DeepEqual(v, transferRequest) {
|
||||
t.Errorf("Request body = %+v, expected %+v", v, transferRequest)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
|
||||
|
||||
})
|
||||
|
||||
transfer, _, err := client.ImageActions.Transfer(12345, transferRequest)
|
||||
if err != nil {
|
||||
t.Errorf("ImageActions.Transfer returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &Action{Status: "in-progress"}
|
||||
if !reflect.DeepEqual(transfer, expected) {
|
||||
t.Errorf("ImageActions.Transfer returned %+v, expected %+v", transfer, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageActions_Get(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/images/123/actions/456", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
|
||||
})
|
||||
|
||||
action, _, err := client.ImageActions.Get(123, 456)
|
||||
if err != nil {
|
||||
t.Errorf("ImageActions.Get returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &Action{Status: "in-progress"}
|
||||
if !reflect.DeepEqual(action, expected) {
|
||||
t.Errorf("ImageActions.Get returned %+v, expected %+v", action, expected)
|
||||
}
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
package godo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestImages_ImagesServiceOpImplementsImagesService(t *testing.T) {
|
||||
if !Implements((*ImagesService)(nil), new(ImagesServiceOp)) {
|
||||
t.Error("ImagesServiceOp does not implement ImagesService")
|
||||
}
|
||||
}
|
||||
|
||||
func TestImages_List(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/images", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"images":[{"id":1},{"id":2}]}`)
|
||||
})
|
||||
|
||||
images, _, err := client.Images.List(nil)
|
||||
if err != nil {
|
||||
t.Errorf("Images.List returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := []Image{{ID: 1}, {ID: 2}}
|
||||
if !reflect.DeepEqual(images, expected) {
|
||||
t.Errorf("Images.List returned %+v, expected %+v", images, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestImages_ListImagesMultiplePages(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/images", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"images": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/images/?page=2"}}}`)
|
||||
})
|
||||
|
||||
_, resp, err := client.Images.List(&ListOptions{Page: 2})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
checkCurrentPage(t, resp, 1)
|
||||
}
|
||||
|
||||
func TestImages_RetrievePageByNumber(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
jBlob := `
|
||||
{
|
||||
"images": [{"id":1},{"id":2}],
|
||||
"links":{
|
||||
"pages":{
|
||||
"next":"http://example.com/v2/images/?page=3",
|
||||
"prev":"http://example.com/v2/images/?page=1",
|
||||
"last":"http://example.com/v2/images/?page=3",
|
||||
"first":"http://example.com/v2/images/?page=1"
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
mux.HandleFunc("/v2/images", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, jBlob)
|
||||
})
|
||||
|
||||
opt := &ListOptions{Page: 2}
|
||||
_, resp, err := client.Images.List(opt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
checkCurrentPage(t, resp, 2)
|
||||
}
|
||||
|
||||
func TestImage_String(t *testing.T) {
|
||||
image := &Image{
|
||||
ID: 1,
|
||||
Name: "Image",
|
||||
Distribution: "Ubuntu",
|
||||
Slug: "image",
|
||||
Public: true,
|
||||
Regions: []string{"one", "two"},
|
||||
}
|
||||
|
||||
stringified := image.String()
|
||||
expected := `godo.Image{ID:1, Name:"Image", Distribution:"Ubuntu", Slug:"image", Public:true, Regions:["one" "two"]}`
|
||||
if expected != stringified {
|
||||
t.Errorf("Image.String returned %+v, expected %+v", stringified, expected)
|
||||
}
|
||||
}
|
|
@ -1,196 +0,0 @@
|
|||
package godo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestKeys_KeysServiceOpImplementsKeysService(t *testing.T) {
|
||||
if !Implements((*KeysService)(nil), new(KeysServiceOp)) {
|
||||
t.Error("KeysServiceOp does not implement KeysService")
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeys_List(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/account/keys", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"ssh_keys":[{"id":1},{"id":2}]}`)
|
||||
})
|
||||
|
||||
keys, _, err := client.Keys.List(nil)
|
||||
if err != nil {
|
||||
t.Errorf("Keys.List returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := []Key{{ID: 1}, {ID: 2}}
|
||||
if !reflect.DeepEqual(keys, expected) {
|
||||
t.Errorf("Keys.List returned %+v, expected %+v", keys, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeys_ListKeysMultiplePages(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/account/keys", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"droplets": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/account/keys/?page=2"}}}`)
|
||||
})
|
||||
|
||||
_, resp, err := client.Keys.List(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
checkCurrentPage(t, resp, 1)
|
||||
}
|
||||
|
||||
func TestKeys_RetrievePageByNumber(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
jBlob := `
|
||||
{
|
||||
"keys": [{"id":1},{"id":2}],
|
||||
"links":{
|
||||
"pages":{
|
||||
"next":"http://example.com/v2/account/keys/?page=3",
|
||||
"prev":"http://example.com/v2/account/keys/?page=1",
|
||||
"last":"http://example.com/v2/account/keys/?page=3",
|
||||
"first":"http://example.com/v2/account/keys/?page=1"
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
mux.HandleFunc("/v2/account/keys", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, jBlob)
|
||||
})
|
||||
|
||||
opt := &ListOptions{Page: 2}
|
||||
_, resp, err := client.Keys.List(opt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
checkCurrentPage(t, resp, 2)
|
||||
}
|
||||
|
||||
func TestKeys_GetByID(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/account/keys/12345", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"ssh_key": {"id":12345}}`)
|
||||
})
|
||||
|
||||
keys, _, err := client.Keys.GetByID(12345)
|
||||
if err != nil {
|
||||
t.Errorf("Keys.GetByID returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &Key{ID: 12345}
|
||||
if !reflect.DeepEqual(keys, expected) {
|
||||
t.Errorf("Keys.GetByID returned %+v, expected %+v", keys, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeys_GetByFingerprint(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/account/keys/aa:bb:cc", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"ssh_key": {"fingerprint":"aa:bb:cc"}}`)
|
||||
})
|
||||
|
||||
keys, _, err := client.Keys.GetByFingerprint("aa:bb:cc")
|
||||
if err != nil {
|
||||
t.Errorf("Keys.GetByFingerprint returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &Key{Fingerprint: "aa:bb:cc"}
|
||||
if !reflect.DeepEqual(keys, expected) {
|
||||
t.Errorf("Keys.GetByFingerprint returned %+v, expected %+v", keys, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeys_Create(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
createRequest := &KeyCreateRequest{
|
||||
Name: "name",
|
||||
PublicKey: "ssh-rsa longtextandstuff",
|
||||
}
|
||||
|
||||
mux.HandleFunc("/v2/account/keys", func(w http.ResponseWriter, r *http.Request) {
|
||||
v := new(KeyCreateRequest)
|
||||
json.NewDecoder(r.Body).Decode(v)
|
||||
|
||||
testMethod(t, r, "POST")
|
||||
if !reflect.DeepEqual(v, createRequest) {
|
||||
t.Errorf("Request body = %+v, expected %+v", v, createRequest)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `{"ssh_key":{"id":1}}`)
|
||||
})
|
||||
|
||||
key, _, err := client.Keys.Create(createRequest)
|
||||
if err != nil {
|
||||
t.Errorf("Keys.Create returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := &Key{ID: 1}
|
||||
if !reflect.DeepEqual(key, expected) {
|
||||
t.Errorf("Keys.Create returned %+v, expected %+v", key, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeys_DestroyByID(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/account/keys/12345", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "DELETE")
|
||||
})
|
||||
|
||||
_, err := client.Keys.DeleteByID(12345)
|
||||
if err != nil {
|
||||
t.Errorf("Keys.Delete returned error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeys_DestroyByFingerprint(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/account/keys/aa:bb:cc", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "DELETE")
|
||||
})
|
||||
|
||||
_, err := client.Keys.DeleteByFingerprint("aa:bb:cc")
|
||||
if err != nil {
|
||||
t.Errorf("Keys.Delete returned error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKey_String(t *testing.T) {
|
||||
key := &Key{
|
||||
ID: 123,
|
||||
Name: "Key",
|
||||
Fingerprint: "fingerprint",
|
||||
PublicKey: "public key",
|
||||
}
|
||||
|
||||
stringified := key.String()
|
||||
expected := `godo.Key{ID:123, Name:"Key", Fingerprint:"fingerprint", PublicKey:"public key"}`
|
||||
if expected != stringified {
|
||||
t.Errorf("Key.String returned %+v, expected %+v", stringified, expected)
|
||||
}
|
||||
}
|
|
@ -1,176 +0,0 @@
|
|||
package godo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
firstPageLinksJSONBlob = []byte(`{
|
||||
"links": {
|
||||
"pages": {
|
||||
"last": "https://api.digitalocean.com/v2/droplets/?page=3",
|
||||
"next": "https://api.digitalocean.com/v2/droplets/?page=2"
|
||||
}
|
||||
}
|
||||
}`)
|
||||
otherPageLinksJSONBlob = []byte(`{
|
||||
"links": {
|
||||
"pages": {
|
||||
"first": "https://api.digitalocean.com/v2/droplets/?page=1",
|
||||
"prev": "https://api.digitalocean.com/v2/droplets/?page=1",
|
||||
"last": "https://api.digitalocean.com/v2/droplets/?page=3",
|
||||
"next": "https://api.digitalocean.com/v2/droplets/?page=3"
|
||||
}
|
||||
}
|
||||
}`)
|
||||
lastPageLinksJSONBlob = []byte(`{
|
||||
"links": {
|
||||
"pages": {
|
||||
"first": "https://api.digitalocean.com/v2/droplets/?page=1",
|
||||
"prev": "https://api.digitalocean.com/v2/droplets/?page=2"
|
||||
}
|
||||
}
|
||||
}`)
|
||||
|
||||
missingLinksJSONBlob = []byte(`{ }`)
|
||||
)
|
||||
|
||||
type godoList struct {
|
||||
Links Links `json:"links"`
|
||||
}
|
||||
|
||||
func loadLinksJSON(t *testing.T, j []byte) Links {
|
||||
var list godoList
|
||||
err := json.Unmarshal(j, &list)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return list.Links
|
||||
}
|
||||
|
||||
func TestLinks_ParseFirst(t *testing.T) {
|
||||
links := loadLinksJSON(t, firstPageLinksJSONBlob)
|
||||
_, err := links.CurrentPage()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
r := &Response{Links: &links}
|
||||
checkCurrentPage(t, r, 1)
|
||||
|
||||
if links.IsLastPage() {
|
||||
t.Fatalf("shouldn't be last page")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinks_ParseMiddle(t *testing.T) {
|
||||
links := loadLinksJSON(t, otherPageLinksJSONBlob)
|
||||
_, err := links.CurrentPage()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
r := &Response{Links: &links}
|
||||
checkCurrentPage(t, r, 2)
|
||||
|
||||
if links.IsLastPage() {
|
||||
t.Fatalf("shouldn't be last page")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinks_ParseLast(t *testing.T) {
|
||||
links := loadLinksJSON(t, lastPageLinksJSONBlob)
|
||||
_, err := links.CurrentPage()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
r := &Response{Links: &links}
|
||||
checkCurrentPage(t, r, 3)
|
||||
if !links.IsLastPage() {
|
||||
t.Fatalf("expected last page")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinks_ParseMissing(t *testing.T) {
|
||||
links := loadLinksJSON(t, missingLinksJSONBlob)
|
||||
_, err := links.CurrentPage()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
r := &Response{Links: &links}
|
||||
checkCurrentPage(t, r, 1)
|
||||
}
|
||||
|
||||
func TestLinks_ParseURL(t *testing.T) {
|
||||
type linkTest struct {
|
||||
name, url string
|
||||
expected int
|
||||
}
|
||||
|
||||
linkTests := []linkTest{
|
||||
{
|
||||
name: "prev",
|
||||
url: "https://api.digitalocean.com/v2/droplets/?page=1",
|
||||
expected: 1,
|
||||
},
|
||||
{
|
||||
name: "last",
|
||||
url: "https://api.digitalocean.com/v2/droplets/?page=5",
|
||||
expected: 5,
|
||||
},
|
||||
{
|
||||
name: "nexta",
|
||||
url: "https://api.digitalocean.com/v2/droplets/?page=2",
|
||||
expected: 2,
|
||||
},
|
||||
}
|
||||
|
||||
for _, lT := range linkTests {
|
||||
p, err := pageForURL(lT.url)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if p != lT.expected {
|
||||
t.Error("expected page for '%s' to be '%d', was '%d'",
|
||||
lT.url, lT.expected, p)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestLinks_ParseEmptyString(t *testing.T) {
|
||||
type linkTest struct {
|
||||
name, url string
|
||||
expected int
|
||||
}
|
||||
|
||||
linkTests := []linkTest{
|
||||
{
|
||||
name: "none",
|
||||
url: "http://example.com",
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
name: "bad",
|
||||
url: "no url",
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
name: "empty",
|
||||
url: "",
|
||||
expected: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, lT := range linkTests {
|
||||
_, err := pageForURL(lT.url)
|
||||
if err == nil {
|
||||
t.Fatalf("expected error for test '%s', but received none", lT.name)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
package godo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRegions_RegionsServiceOpImplementsRegionsService(t *testing.T) {
|
||||
if !Implements((*RegionsService)(nil), new(RegionsServiceOp)) {
|
||||
t.Error("RegionsServiceOp does not implement RegionsService")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegions_List(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/regions", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"regions":[{"slug":"1"},{"slug":"2"}]}`)
|
||||
})
|
||||
|
||||
regions, _, err := client.Regions.List(nil)
|
||||
if err != nil {
|
||||
t.Errorf("Regions.List returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := []Region{{Slug: "1"}, {Slug: "2"}}
|
||||
if !reflect.DeepEqual(regions, expected) {
|
||||
t.Errorf("Regions.List returned %+v, expected %+v", regions, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegions_ListRegionsMultiplePages(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/regions", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"regions": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/regions/?page=2"}}}`)
|
||||
})
|
||||
|
||||
_, resp, err := client.Regions.List(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
checkCurrentPage(t, resp, 1)
|
||||
}
|
||||
|
||||
func TestRegions_RetrievePageByNumber(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
jBlob := `
|
||||
{
|
||||
"regions": [{"id":1},{"id":2}],
|
||||
"links":{
|
||||
"pages":{
|
||||
"next":"http://example.com/v2/regions/?page=3",
|
||||
"prev":"http://example.com/v2/regions/?page=1",
|
||||
"last":"http://example.com/v2/regions/?page=3",
|
||||
"first":"http://example.com/v2/regions/?page=1"
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
mux.HandleFunc("/v2/regions", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, jBlob)
|
||||
})
|
||||
|
||||
opt := &ListOptions{Page: 2}
|
||||
_, resp, err := client.Regions.List(opt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
checkCurrentPage(t, resp, 2)
|
||||
}
|
||||
|
||||
func TestRegion_String(t *testing.T) {
|
||||
region := &Region{
|
||||
Slug: "region",
|
||||
Name: "Region",
|
||||
Sizes: []string{"1", "2"},
|
||||
Available: true,
|
||||
}
|
||||
|
||||
stringified := region.String()
|
||||
expected := `godo.Region{Slug:"region", Name:"Region", Sizes:["1" "2"], Available:true}`
|
||||
if expected != stringified {
|
||||
t.Errorf("Region.String returned %+v, expected %+v", stringified, expected)
|
||||
}
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
package godo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSizes_SizesServiceOpImplementsSizesService(t *testing.T) {
|
||||
if !Implements((*SizesService)(nil), new(SizesServiceOp)) {
|
||||
t.Error("SizesServiceOp does not implement SizesService")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSizes_List(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/sizes", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"sizes":[{"slug":"1"},{"slug":"2"}]}`)
|
||||
})
|
||||
|
||||
sizes, _, err := client.Sizes.List(nil)
|
||||
if err != nil {
|
||||
t.Errorf("Sizes.List returned error: %v", err)
|
||||
}
|
||||
|
||||
expected := []Size{{Slug: "1"}, {Slug: "2"}}
|
||||
if !reflect.DeepEqual(sizes, expected) {
|
||||
t.Errorf("Sizes.List returned %+v, expected %+v", sizes, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSizes_ListSizesMultiplePages(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v2/sizes", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, `{"sizes": [{"id":1},{"id":2}], "links":{"pages":{"next":"http://example.com/v2/sizes/?page=2"}}}`)
|
||||
})
|
||||
|
||||
_, resp, err := client.Sizes.List(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
checkCurrentPage(t, resp, 1)
|
||||
}
|
||||
|
||||
func TestSizes_RetrievePageByNumber(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
jBlob := `
|
||||
{
|
||||
"sizes": [{"id":1},{"id":2}],
|
||||
"links":{
|
||||
"pages":{
|
||||
"next":"http://example.com/v2/sizes/?page=3",
|
||||
"prev":"http://example.com/v2/sizes/?page=1",
|
||||
"last":"http://example.com/v2/sizes/?page=3",
|
||||
"first":"http://example.com/v2/sizes/?page=1"
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
mux.HandleFunc("/v2/sizes", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
fmt.Fprint(w, jBlob)
|
||||
})
|
||||
|
||||
opt := &ListOptions{Page: 2}
|
||||
_, resp, err := client.Sizes.List(opt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
checkCurrentPage(t, resp, 2)
|
||||
}
|
||||
|
||||
func TestSize_String(t *testing.T) {
|
||||
size := &Size{
|
||||
Slug: "slize",
|
||||
Memory: 123,
|
||||
Vcpus: 456,
|
||||
Disk: 789,
|
||||
PriceMonthly: 123,
|
||||
PriceHourly: 456,
|
||||
Regions: []string{"1", "2"},
|
||||
}
|
||||
|
||||
stringified := size.String()
|
||||
expected := `godo.Size{Slug:"slize", Memory:123, Vcpus:456, Disk:789, PriceMonthly:123, PriceHourly:456, Regions:["1" "2"]}`
|
||||
if expected != stringified {
|
||||
t.Errorf("Size.String returned %+v, expected %+v", stringified, expected)
|
||||
}
|
||||
}
|
|
@ -1,176 +0,0 @@
|
|||
package godo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
emptyTimeStr = `"0001-01-01T00:00:00Z"`
|
||||
referenceTimeStr = `"2006-01-02T15:04:05Z"`
|
||||
referenceUnixTimeStr = `1136214245`
|
||||
)
|
||||
|
||||
var (
|
||||
referenceTime = time.Date(2006, 01, 02, 15, 04, 05, 0, time.UTC)
|
||||
unixOrigin = time.Unix(0, 0).In(time.UTC)
|
||||
)
|
||||
|
||||
func TestTimestamp_Marshal(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
data Timestamp
|
||||
want string
|
||||
wantErr bool
|
||||
equal bool
|
||||
}{
|
||||
{"Reference", Timestamp{referenceTime}, referenceTimeStr, false, true},
|
||||
{"Empty", Timestamp{}, emptyTimeStr, false, true},
|
||||
{"Mismatch", Timestamp{}, referenceTimeStr, false, false},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
out, err := json.Marshal(tc.data)
|
||||
if gotErr := (err != nil); gotErr != tc.wantErr {
|
||||
t.Errorf("%s: gotErr=%v, wantErr=%v, err=%v", tc.desc, gotErr, tc.wantErr, err)
|
||||
}
|
||||
got := string(out)
|
||||
equal := got == tc.want
|
||||
if (got == tc.want) != tc.equal {
|
||||
t.Errorf("%s: got=%s, want=%s, equal=%v, want=%v", tc.desc, got, tc.want, equal, tc.equal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimestamp_Unmarshal(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
data string
|
||||
want Timestamp
|
||||
wantErr bool
|
||||
equal bool
|
||||
}{
|
||||
{"Reference", referenceTimeStr, Timestamp{referenceTime}, false, true},
|
||||
{"ReferenceUnix", `1136214245`, Timestamp{referenceTime}, false, true},
|
||||
{"Empty", emptyTimeStr, Timestamp{}, false, true},
|
||||
{"UnixStart", `0`, Timestamp{unixOrigin}, false, true},
|
||||
{"Mismatch", referenceTimeStr, Timestamp{}, false, false},
|
||||
{"MismatchUnix", `0`, Timestamp{}, false, false},
|
||||
{"Invalid", `"asdf"`, Timestamp{referenceTime}, true, false},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
var got Timestamp
|
||||
err := json.Unmarshal([]byte(tc.data), &got)
|
||||
if gotErr := err != nil; gotErr != tc.wantErr {
|
||||
t.Errorf("%s: gotErr=%v, wantErr=%v, err=%v", tc.desc, gotErr, tc.wantErr, err)
|
||||
continue
|
||||
}
|
||||
equal := got.Equal(tc.want)
|
||||
if equal != tc.equal {
|
||||
t.Errorf("%s: got=%#v, want=%#v, equal=%v, want=%v", tc.desc, got, tc.want, equal, tc.equal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimstamp_MarshalReflexivity(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
data Timestamp
|
||||
}{
|
||||
{"Reference", Timestamp{referenceTime}},
|
||||
{"Empty", Timestamp{}},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
data, err := json.Marshal(tc.data)
|
||||
if err != nil {
|
||||
t.Errorf("%s: Marshal err=%v", tc.desc, err)
|
||||
}
|
||||
var got Timestamp
|
||||
err = json.Unmarshal(data, &got)
|
||||
if !got.Equal(tc.data) {
|
||||
t.Errorf("%s: %+v != %+v", tc.desc, got, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type WrappedTimestamp struct {
|
||||
A int
|
||||
Time Timestamp
|
||||
}
|
||||
|
||||
func TestWrappedTimstamp_Marshal(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
data WrappedTimestamp
|
||||
want string
|
||||
wantErr bool
|
||||
equal bool
|
||||
}{
|
||||
{"Reference", WrappedTimestamp{0, Timestamp{referenceTime}}, fmt.Sprintf(`{"A":0,"Time":%s}`, referenceTimeStr), false, true},
|
||||
{"Empty", WrappedTimestamp{}, fmt.Sprintf(`{"A":0,"Time":%s}`, emptyTimeStr), false, true},
|
||||
{"Mismatch", WrappedTimestamp{}, fmt.Sprintf(`{"A":0,"Time":%s}`, referenceTimeStr), false, false},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
out, err := json.Marshal(tc.data)
|
||||
if gotErr := err != nil; gotErr != tc.wantErr {
|
||||
t.Errorf("%s: gotErr=%v, wantErr=%v, err=%v", tc.desc, gotErr, tc.wantErr, err)
|
||||
}
|
||||
got := string(out)
|
||||
equal := got == tc.want
|
||||
if equal != tc.equal {
|
||||
t.Errorf("%s: got=%s, want=%s, equal=%v, want=%v", tc.desc, got, tc.want, equal, tc.equal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrappedTimestamp_Unmarshal(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
data string
|
||||
want WrappedTimestamp
|
||||
wantErr bool
|
||||
equal bool
|
||||
}{
|
||||
{"Reference", referenceTimeStr, WrappedTimestamp{0, Timestamp{referenceTime}}, false, true},
|
||||
{"ReferenceUnix", referenceUnixTimeStr, WrappedTimestamp{0, Timestamp{referenceTime}}, false, true},
|
||||
{"Empty", emptyTimeStr, WrappedTimestamp{0, Timestamp{}}, false, true},
|
||||
{"UnixStart", `0`, WrappedTimestamp{0, Timestamp{unixOrigin}}, false, true},
|
||||
{"Mismatch", referenceTimeStr, WrappedTimestamp{0, Timestamp{}}, false, false},
|
||||
{"MismatchUnix", `0`, WrappedTimestamp{0, Timestamp{}}, false, false},
|
||||
{"Invalid", `"asdf"`, WrappedTimestamp{0, Timestamp{referenceTime}}, true, false},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
var got Timestamp
|
||||
err := json.Unmarshal([]byte(tc.data), &got)
|
||||
if gotErr := err != nil; gotErr != tc.wantErr {
|
||||
t.Errorf("%s: gotErr=%v, wantErr=%v, err=%v", tc.desc, gotErr, tc.wantErr, err)
|
||||
continue
|
||||
}
|
||||
equal := got.Time.Equal(tc.want.Time.Time)
|
||||
if equal != tc.equal {
|
||||
t.Errorf("%s: got=%#v, want=%#v, equal=%v, want=%v", tc.desc, got, tc.want, equal, tc.equal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrappedTimestamp_MarshalReflexivity(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
data WrappedTimestamp
|
||||
}{
|
||||
{"Reference", WrappedTimestamp{0, Timestamp{referenceTime}}},
|
||||
{"Empty", WrappedTimestamp{0, Timestamp{}}},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
bytes, err := json.Marshal(tc.data)
|
||||
if err != nil {
|
||||
t.Errorf("%s: Marshal err=%v", tc.desc, err)
|
||||
}
|
||||
var got WrappedTimestamp
|
||||
err = json.Unmarshal(bytes, &got)
|
||||
if !got.Time.Equal(tc.data.Time) {
|
||||
t.Errorf("%s: %+v != %+v", tc.desc, got, tc.data)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,191 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright 2013-2015 Docker, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,19 @@
|
|||
Docker
|
||||
Copyright 2012-2014 Docker, Inc.
|
||||
|
||||
This product includes software developed at Docker, Inc. (http://www.docker.com).
|
||||
|
||||
This product contains software (https://github.com/kr/pty) developed
|
||||
by Keith Rarick, licensed under the MIT License.
|
||||
|
||||
The following is courtesy of our legal counsel:
|
||||
|
||||
|
||||
Use and transfer of Docker may be subject to certain restrictions by the
|
||||
United States and other governments.
|
||||
It is your responsibility to ensure that your use and/or transfer does not
|
||||
violate applicable laws.
|
||||
|
||||
For more information, please see http://www.bis.doc.gov
|
||||
|
||||
See also http://www.apache.org/dev/crypto.html and/or seek legal counsel.
|
|
@ -0,0 +1,22 @@
|
|||
Copyright (c) 2013 Honza Pokorny
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,27 @@
|
|||
Copyright (c) 2014-2015 The Docker & Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,191 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright 2014-2015 Docker, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,27 @@
|
|||
Copyright (c) 2014-2015 The Docker & Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
vendor/github.com/docker/docker/vendor/src/code.google.com/p/go.net/LICENSE
generated
vendored
Normal file
27
vendor/github.com/docker/docker/vendor/src/code.google.com/p/go.net/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
22
vendor/github.com/docker/docker/vendor/src/code.google.com/p/go.net/PATENTS
generated
vendored
Normal file
22
vendor/github.com/docker/docker/vendor/src/code.google.com/p/go.net/PATENTS
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
Additional IP Rights Grant (Patents)
|
||||
|
||||
"This implementation" means the copyrightable works distributed by
|
||||
Google as part of the Go project.
|
||||
|
||||
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||
patent license to make, have made, use, offer to sell, sell, import,
|
||||
transfer and otherwise run, modify and propagate the contents of this
|
||||
implementation of Go, where such license applies only to those patent
|
||||
claims, both currently owned or controlled by Google and acquired in
|
||||
the future, licensable by Google that are necessarily infringed by this
|
||||
implementation of Go. This grant does not include claims that would be
|
||||
infringed only as a consequence of further modification of this
|
||||
implementation. If you or your agent or exclusive licensee institute or
|
||||
order or agree to the institution of patent litigation against any
|
||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that this implementation of Go or any code incorporated within this
|
||||
implementation of Go constitutes direct or contributory patent
|
||||
infringement, or inducement of patent infringement, then any patent
|
||||
rights granted to you under this License for this implementation of Go
|
||||
shall terminate as of the date such litigation is filed.
|
21
vendor/github.com/docker/docker/vendor/src/github.com/Sirupsen/logrus/LICENSE
generated
vendored
Normal file
21
vendor/github.com/docker/docker/vendor/src/github.com/Sirupsen/logrus/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Simon Eskildsen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
191
vendor/github.com/docker/docker/vendor/src/github.com/coreos/go-systemd/LICENSE
generated
vendored
Normal file
191
vendor/github.com/docker/docker/vendor/src/github.com/coreos/go-systemd/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,191 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and
|
||||
distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
||||
owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities
|
||||
that control, are controlled by, or are under common control with that entity.
|
||||
For the purposes of this definition, "control" means (i) the power, direct or
|
||||
indirect, to cause the direction or management of such entity, whether by
|
||||
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
||||
permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including
|
||||
but not limited to software source code, documentation source, and configuration
|
||||
files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or
|
||||
translation of a Source form, including but not limited to compiled object code,
|
||||
generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made
|
||||
available under the License, as indicated by a copyright notice that is included
|
||||
in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that
|
||||
is based on (or derived from) the Work and for which the editorial revisions,
|
||||
annotations, elaborations, or other modifications represent, as a whole, an
|
||||
original work of authorship. For the purposes of this License, Derivative Works
|
||||
shall not include works that remain separable from, or merely link (or bind by
|
||||
name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version
|
||||
of the Work and any modifications or additions to that Work or Derivative Works
|
||||
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
||||
by the copyright owner or by an individual or Legal Entity authorized to submit
|
||||
on behalf of the copyright owner. For the purposes of this definition,
|
||||
"submitted" means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems, and
|
||||
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
||||
the purpose of discussing and improving the Work, but excluding communication
|
||||
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||
owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
||||
of whom a Contribution has been received by Licensor and subsequently
|
||||
incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the Work and such
|
||||
Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable (except as stated in this section) patent license to make, have
|
||||
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
|
||||
such license applies only to those patent claims licensable by such Contributor
|
||||
that are necessarily infringed by their Contribution(s) alone or by combination
|
||||
of their Contribution(s) with the Work to which such Contribution(s) was
|
||||
submitted. If You institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
|
||||
Contribution incorporated within the Work constitutes direct or contributory
|
||||
patent infringement, then any patent licenses granted to You under this License
|
||||
for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution.
|
||||
|
||||
You may reproduce and distribute copies of the Work or Derivative Works thereof
|
||||
in any medium, with or without modifications, and in Source or Object form,
|
||||
provided that You meet the following conditions:
|
||||
|
||||
You must give any other recipients of the Work or Derivative Works a copy of
|
||||
this License; and
|
||||
You must cause any modified files to carry prominent notices stating that You
|
||||
changed the files; and
|
||||
You must retain, in the Source form of any Derivative Works that You distribute,
|
||||
all copyright, patent, trademark, and attribution notices from the Source form
|
||||
of the Work, excluding those notices that do not pertain to any part of the
|
||||
Derivative Works; and
|
||||
If the Work includes a "NOTICE" text file as part of its distribution, then any
|
||||
Derivative Works that You distribute must include a readable copy of the
|
||||
attribution notices contained within such NOTICE file, excluding those notices
|
||||
that do not pertain to any part of the Derivative Works, in at least one of the
|
||||
following places: within a NOTICE text file distributed as part of the
|
||||
Derivative Works; within the Source form or documentation, if provided along
|
||||
with the Derivative Works; or, within a display generated by the Derivative
|
||||
Works, if and wherever such third-party notices normally appear. The contents of
|
||||
the NOTICE file are for informational purposes only and do not modify the
|
||||
License. You may add Your own attribution notices within Derivative Works that
|
||||
You distribute, alongside or as an addendum to the NOTICE text from the Work,
|
||||
provided that such additional attribution notices cannot be construed as
|
||||
modifying the License.
|
||||
You may add Your own copyright statement to Your modifications and may provide
|
||||
additional or different license terms and conditions for use, reproduction, or
|
||||
distribution of Your modifications, or for any such Derivative Works as a whole,
|
||||
provided Your use, reproduction, and distribution of the Work otherwise complies
|
||||
with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions.
|
||||
|
||||
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
||||
for inclusion in the Work by You to the Licensor shall be under the terms and
|
||||
conditions of this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
||||
any separate license agreement you may have executed with Licensor regarding
|
||||
such Contributions.
|
||||
|
||||
6. Trademarks.
|
||||
|
||||
This License does not grant permission to use the trade names, trademarks,
|
||||
service marks, or product names of the Licensor, except as required for
|
||||
reasonable and customary use in describing the origin of the Work and
|
||||
reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, Licensor provides the
|
||||
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
||||
including, without limitation, any warranties or conditions of TITLE,
|
||||
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
||||
solely responsible for determining the appropriateness of using or
|
||||
redistributing the Work and assume any risks associated with Your exercise of
|
||||
permissions under this License.
|
||||
|
||||
8. Limitation of Liability.
|
||||
|
||||
In no event and under no legal theory, whether in tort (including negligence),
|
||||
contract, or otherwise, unless required by applicable law (such as deliberate
|
||||
and grossly negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special, incidental,
|
||||
or consequential damages of any character arising as a result of this License or
|
||||
out of the use or inability to use the Work (including but not limited to
|
||||
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
|
||||
any and all other commercial damages or losses), even if such Contributor has
|
||||
been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability.
|
||||
|
||||
While redistributing the Work or Derivative Works thereof, You may choose to
|
||||
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
|
||||
other liability obligations and/or rights consistent with this License. However,
|
||||
in accepting such obligations, You may act only on Your own behalf and on Your
|
||||
sole responsibility, not on behalf of any other Contributor, and only if You
|
||||
agree to indemnify, defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason of your
|
||||
accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work
|
||||
|
||||
To apply the Apache License to your work, attach the following boilerplate
|
||||
notice, with the fields enclosed by brackets "[]" replaced with your own
|
||||
identifying information. (Don't include the brackets!) The text should be
|
||||
enclosed in the appropriate comment syntax for the file format. We also
|
||||
recommend that a file or class name and description of purpose be included on
|
||||
the same "printed page" as the copyright notice for easier identification within
|
||||
third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
191
vendor/github.com/docker/docker/vendor/src/github.com/docker/libcontainer/LICENSE
generated
vendored
Normal file
191
vendor/github.com/docker/docker/vendor/src/github.com/docker/libcontainer/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,191 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright 2014 Docker, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
16
vendor/github.com/docker/docker/vendor/src/github.com/docker/libcontainer/NOTICE
generated
vendored
Normal file
16
vendor/github.com/docker/docker/vendor/src/github.com/docker/libcontainer/NOTICE
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
libcontainer
|
||||
Copyright 2012-2014 Docker, Inc.
|
||||
|
||||
This product includes software developed at Docker, Inc. (http://www.docker.com).
|
||||
|
||||
The following is courtesy of our legal counsel:
|
||||
|
||||
|
||||
Use and transfer of Docker may be subject to certain restrictions by the
|
||||
United States and other governments.
|
||||
It is your responsibility to ensure that your use and/or transfer does not
|
||||
violate applicable laws.
|
||||
|
||||
For more information, please see http://www.bis.doc.gov
|
||||
|
||||
See also http://www.apache.org/dev/crypto.html and/or seek legal counsel.
|
191
vendor/github.com/docker/docker/vendor/src/github.com/docker/libtrust/LICENSE
generated
vendored
Normal file
191
vendor/github.com/docker/docker/vendor/src/github.com/docker/libtrust/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,191 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright 2014 Docker, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
28
vendor/github.com/docker/docker/vendor/src/github.com/go-fsnotify/fsnotify/LICENSE
generated
vendored
Normal file
28
vendor/github.com/docker/docker/vendor/src/github.com/go-fsnotify/fsnotify/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
Copyright (c) 2012 fsnotify Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
25
vendor/github.com/docker/docker/vendor/src/github.com/godbus/dbus/LICENSE
generated
vendored
Normal file
25
vendor/github.com/docker/docker/vendor/src/github.com/godbus/dbus/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2013, Georg Reinke (<guelfey at gmail dot com>)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
vendor/github.com/docker/docker/vendor/src/github.com/gorilla/context/LICENSE
generated
vendored
Normal file
27
vendor/github.com/docker/docker/vendor/src/github.com/gorilla/context/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
Copyright (c) 2012 Rodrigo Moraes. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
vendor/github.com/docker/docker/vendor/src/github.com/gorilla/mux/LICENSE
generated
vendored
Normal file
27
vendor/github.com/docker/docker/vendor/src/github.com/gorilla/mux/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
Copyright (c) 2012 Rodrigo Moraes. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
23
vendor/github.com/docker/docker/vendor/src/github.com/kr/pty/License
generated
vendored
Normal file
23
vendor/github.com/docker/docker/vendor/src/github.com/kr/pty/License
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
Copyright (c) 2011 Keith Rarick
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall
|
||||
be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
vendor/github.com/docker/docker/vendor/src/github.com/syndtr/gocapability/LICENSE
generated
vendored
Normal file
24
vendor/github.com/docker/docker/vendor/src/github.com/syndtr/gocapability/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
Copyright 2013 Suryandaru Triandana <syndtr@gmail.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
20
vendor/github.com/docker/docker/vendor/src/github.com/tchap/go-patricia/LICENSE
generated
vendored
Normal file
20
vendor/github.com/docker/docker/vendor/src/github.com/tchap/go-patricia/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 The AUTHORS
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,27 @@
|
|||
Copyright (c) 2013 Google. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,238 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package query
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestValues_types(t *testing.T) {
|
||||
str := "string"
|
||||
strPtr := &str
|
||||
|
||||
tests := []struct {
|
||||
in interface{}
|
||||
want url.Values
|
||||
}{
|
||||
{
|
||||
// basic primitives
|
||||
struct {
|
||||
A string
|
||||
B int
|
||||
C uint
|
||||
D float32
|
||||
E bool
|
||||
}{},
|
||||
url.Values{
|
||||
"A": {""},
|
||||
"B": {"0"},
|
||||
"C": {"0"},
|
||||
"D": {"0"},
|
||||
"E": {"false"},
|
||||
},
|
||||
},
|
||||
{
|
||||
// pointers
|
||||
struct {
|
||||
A *string
|
||||
B *int
|
||||
C **string
|
||||
}{A: strPtr, C: &strPtr},
|
||||
url.Values{
|
||||
"A": {str},
|
||||
"B": {""},
|
||||
"C": {str},
|
||||
},
|
||||
},
|
||||
{
|
||||
// slices and arrays
|
||||
struct {
|
||||
A []string
|
||||
B []string `url:",comma"`
|
||||
C []string `url:",space"`
|
||||
D [2]string
|
||||
E [2]string `url:",comma"`
|
||||
F [2]string `url:",space"`
|
||||
G []*string `url:",space"`
|
||||
H []bool `url:",int,space"`
|
||||
}{
|
||||
A: []string{"a", "b"},
|
||||
B: []string{"a", "b"},
|
||||
C: []string{"a", "b"},
|
||||
D: [2]string{"a", "b"},
|
||||
E: [2]string{"a", "b"},
|
||||
F: [2]string{"a", "b"},
|
||||
G: []*string{&str, &str},
|
||||
H: []bool{true, false},
|
||||
},
|
||||
url.Values{
|
||||
"A": {"a", "b"},
|
||||
"B": {"a,b"},
|
||||
"C": {"a b"},
|
||||
"D": {"a", "b"},
|
||||
"E": {"a,b"},
|
||||
"F": {"a b"},
|
||||
"G": {"string string"},
|
||||
"H": {"1 0"},
|
||||
},
|
||||
},
|
||||
{
|
||||
// other types
|
||||
struct {
|
||||
A time.Time
|
||||
B time.Time `url:",unix"`
|
||||
C bool `url:",int"`
|
||||
D bool `url:",int"`
|
||||
}{
|
||||
A: time.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC),
|
||||
B: time.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC),
|
||||
C: true,
|
||||
D: false,
|
||||
},
|
||||
url.Values{
|
||||
"A": {"2000-01-01T12:34:56Z"},
|
||||
"B": {"946730096"},
|
||||
"C": {"1"},
|
||||
"D": {"0"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
v, err := Values(tt.in)
|
||||
if err != nil {
|
||||
t.Errorf("%d. Values(%q) returned error: %v", i, tt.in, err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tt.want, v) {
|
||||
t.Errorf("%d. Values(%q) returned %v, want %v", i, tt.in, v, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValues_omitEmpty(t *testing.T) {
|
||||
str := ""
|
||||
s := struct {
|
||||
a string
|
||||
A string
|
||||
B string `url:",omitempty"`
|
||||
C string `url:"-"`
|
||||
D string `url:"omitempty"` // actually named omitempty, not an option
|
||||
E *string `url:",omitempty"`
|
||||
}{E: &str}
|
||||
|
||||
v, err := Values(s)
|
||||
if err != nil {
|
||||
t.Errorf("Values(%q) returned error: %v", s, err)
|
||||
}
|
||||
|
||||
want := url.Values{
|
||||
"A": {""},
|
||||
"omitempty": {""},
|
||||
"E": {""}, // E is included because the pointer is not empty, even though the string being pointed to is
|
||||
}
|
||||
if !reflect.DeepEqual(want, v) {
|
||||
t.Errorf("Values(%q) returned %v, want %v", s, v, want)
|
||||
}
|
||||
}
|
||||
|
||||
type A struct {
|
||||
B
|
||||
}
|
||||
|
||||
type B struct {
|
||||
C string
|
||||
}
|
||||
|
||||
type D struct {
|
||||
B
|
||||
C string
|
||||
}
|
||||
|
||||
func TestValues_embeddedStructs(t *testing.T) {
|
||||
tests := []struct {
|
||||
in interface{}
|
||||
want url.Values
|
||||
}{
|
||||
{
|
||||
A{B{C: "foo"}},
|
||||
url.Values{"C": {"foo"}},
|
||||
},
|
||||
{
|
||||
D{B: B{C: "bar"}, C: "foo"},
|
||||
url.Values{"C": {"foo", "bar"}},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
v, err := Values(tt.in)
|
||||
if err != nil {
|
||||
t.Errorf("%d. Values(%q) returned error: %v", i, tt.in, err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tt.want, v) {
|
||||
t.Errorf("%d. Values(%q) returned %v, want %v", i, tt.in, v, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValues_invalidInput(t *testing.T) {
|
||||
_, err := Values("")
|
||||
if err == nil {
|
||||
t.Errorf("expected Values() to return an error on invalid input")
|
||||
}
|
||||
}
|
||||
|
||||
type EncodedArgs []string
|
||||
|
||||
func (m EncodedArgs) EncodeValues(v *url.Values) error {
|
||||
for i, arg := range m {
|
||||
v.Set(fmt.Sprintf("arg.%d", i), arg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestValues_Marshaler(t *testing.T) {
|
||||
s := struct {
|
||||
Args EncodedArgs `url:"args"`
|
||||
}{[]string{"a", "b", "c"}}
|
||||
v, err := Values(s)
|
||||
if err != nil {
|
||||
t.Errorf("Values(%q) returned error: %v", s, err)
|
||||
}
|
||||
|
||||
want := url.Values{
|
||||
"arg.0": {"a"},
|
||||
"arg.1": {"b"},
|
||||
"arg.2": {"c"},
|
||||
}
|
||||
if !reflect.DeepEqual(want, v) {
|
||||
t.Errorf("Values(%q) returned %v, want %v", s, v, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTagParsing(t *testing.T) {
|
||||
name, opts := parseTag("field,foobar,foo")
|
||||
if name != "field" {
|
||||
t.Fatalf("name = %q, want field", name)
|
||||
}
|
||||
for _, tt := range []struct {
|
||||
opt string
|
||||
want bool
|
||||
}{
|
||||
{"foobar", true},
|
||||
{"foo", true},
|
||||
{"bar", false},
|
||||
{"field", false},
|
||||
} {
|
||||
if opts.Contains(tt.opt) != tt.want {
|
||||
t.Errorf("Contains(%q) = %v", tt.opt, !tt.want)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,191 +0,0 @@
|
|||
package mapstructure
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestComposeDecodeHookFunc(t *testing.T) {
|
||||
f1 := func(
|
||||
f reflect.Kind,
|
||||
t reflect.Kind,
|
||||
data interface{}) (interface{}, error) {
|
||||
return data.(string) + "foo", nil
|
||||
}
|
||||
|
||||
f2 := func(
|
||||
f reflect.Kind,
|
||||
t reflect.Kind,
|
||||
data interface{}) (interface{}, error) {
|
||||
return data.(string) + "bar", nil
|
||||
}
|
||||
|
||||
f := ComposeDecodeHookFunc(f1, f2)
|
||||
|
||||
result, err := f(reflect.String, reflect.Slice, "")
|
||||
if err != nil {
|
||||
t.Fatalf("bad: %s", err)
|
||||
}
|
||||
if result.(string) != "foobar" {
|
||||
t.Fatalf("bad: %#v", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestComposeDecodeHookFunc_err(t *testing.T) {
|
||||
f1 := func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) {
|
||||
return nil, errors.New("foo")
|
||||
}
|
||||
|
||||
f2 := func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) {
|
||||
panic("NOPE")
|
||||
}
|
||||
|
||||
f := ComposeDecodeHookFunc(f1, f2)
|
||||
|
||||
_, err := f(reflect.String, reflect.Slice, 42)
|
||||
if err.Error() != "foo" {
|
||||
t.Fatalf("bad: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestComposeDecodeHookFunc_kinds(t *testing.T) {
|
||||
var f2From reflect.Kind
|
||||
|
||||
f1 := func(
|
||||
f reflect.Kind,
|
||||
t reflect.Kind,
|
||||
data interface{}) (interface{}, error) {
|
||||
return int(42), nil
|
||||
}
|
||||
|
||||
f2 := func(
|
||||
f reflect.Kind,
|
||||
t reflect.Kind,
|
||||
data interface{}) (interface{}, error) {
|
||||
f2From = f
|
||||
return data, nil
|
||||
}
|
||||
|
||||
f := ComposeDecodeHookFunc(f1, f2)
|
||||
|
||||
_, err := f(reflect.String, reflect.Slice, "")
|
||||
if err != nil {
|
||||
t.Fatalf("bad: %s", err)
|
||||
}
|
||||
if f2From != reflect.Int {
|
||||
t.Fatalf("bad: %#v", f2From)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringToSliceHookFunc(t *testing.T) {
|
||||
f := StringToSliceHookFunc(",")
|
||||
|
||||
cases := []struct {
|
||||
f, t reflect.Kind
|
||||
data interface{}
|
||||
result interface{}
|
||||
err bool
|
||||
}{
|
||||
{reflect.Slice, reflect.Slice, 42, 42, false},
|
||||
{reflect.String, reflect.String, 42, 42, false},
|
||||
{
|
||||
reflect.String,
|
||||
reflect.Slice,
|
||||
"foo,bar,baz",
|
||||
[]string{"foo", "bar", "baz"},
|
||||
false,
|
||||
},
|
||||
{
|
||||
reflect.String,
|
||||
reflect.Slice,
|
||||
"",
|
||||
[]string{},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
actual, err := f(tc.f, tc.t, tc.data)
|
||||
if tc.err != (err != nil) {
|
||||
t.Fatalf("case %d: expected err %#v", i, tc.err)
|
||||
}
|
||||
if !reflect.DeepEqual(actual, tc.result) {
|
||||
t.Fatalf(
|
||||
"case %d: expected %#v, got %#v",
|
||||
i, tc.result, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWeaklyTypedHook(t *testing.T) {
|
||||
var f DecodeHookFunc = WeaklyTypedHook
|
||||
|
||||
cases := []struct {
|
||||
f, t reflect.Kind
|
||||
data interface{}
|
||||
result interface{}
|
||||
err bool
|
||||
}{
|
||||
// TO STRING
|
||||
{
|
||||
reflect.Bool,
|
||||
reflect.String,
|
||||
false,
|
||||
"0",
|
||||
false,
|
||||
},
|
||||
|
||||
{
|
||||
reflect.Bool,
|
||||
reflect.String,
|
||||
true,
|
||||
"1",
|
||||
false,
|
||||
},
|
||||
|
||||
{
|
||||
reflect.Float32,
|
||||
reflect.String,
|
||||
float32(7),
|
||||
"7",
|
||||
false,
|
||||
},
|
||||
|
||||
{
|
||||
reflect.Int,
|
||||
reflect.String,
|
||||
int(7),
|
||||
"7",
|
||||
false,
|
||||
},
|
||||
|
||||
{
|
||||
reflect.Slice,
|
||||
reflect.String,
|
||||
[]uint8("foo"),
|
||||
"foo",
|
||||
false,
|
||||
},
|
||||
|
||||
{
|
||||
reflect.Uint,
|
||||
reflect.String,
|
||||
uint(7),
|
||||
"7",
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
actual, err := f(tc.f, tc.t, tc.data)
|
||||
if tc.err != (err != nil) {
|
||||
t.Fatalf("case %d: expected err %#v", i, tc.err)
|
||||
}
|
||||
if !reflect.DeepEqual(actual, tc.result) {
|
||||
t.Fatalf(
|
||||
"case %d: expected %#v, got %#v",
|
||||
i, tc.result, actual)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,243 +0,0 @@
|
|||
package mapstructure
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Benchmark_Decode(b *testing.B) {
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
Emails []string
|
||||
Extra map[string]string
|
||||
}
|
||||
|
||||
input := map[string]interface{}{
|
||||
"name": "Mitchell",
|
||||
"age": 91,
|
||||
"emails": []string{"one", "two", "three"},
|
||||
"extra": map[string]string{
|
||||
"twitter": "mitchellh",
|
||||
},
|
||||
}
|
||||
|
||||
var result Person
|
||||
for i := 0; i < b.N; i++ {
|
||||
Decode(input, &result)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_DecodeBasic(b *testing.B) {
|
||||
input := map[string]interface{}{
|
||||
"vstring": "foo",
|
||||
"vint": 42,
|
||||
"Vuint": 42,
|
||||
"vbool": true,
|
||||
"Vfloat": 42.42,
|
||||
"vsilent": true,
|
||||
"vdata": 42,
|
||||
}
|
||||
|
||||
var result Basic
|
||||
for i := 0; i < b.N; i++ {
|
||||
Decode(input, &result)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_DecodeEmbedded(b *testing.B) {
|
||||
input := map[string]interface{}{
|
||||
"vstring": "foo",
|
||||
"Basic": map[string]interface{}{
|
||||
"vstring": "innerfoo",
|
||||
},
|
||||
"vunique": "bar",
|
||||
}
|
||||
|
||||
var result Embedded
|
||||
for i := 0; i < b.N; i++ {
|
||||
Decode(input, &result)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_DecodeTypeConversion(b *testing.B) {
|
||||
input := map[string]interface{}{
|
||||
"IntToFloat": 42,
|
||||
"IntToUint": 42,
|
||||
"IntToBool": 1,
|
||||
"IntToString": 42,
|
||||
"UintToInt": 42,
|
||||
"UintToFloat": 42,
|
||||
"UintToBool": 42,
|
||||
"UintToString": 42,
|
||||
"BoolToInt": true,
|
||||
"BoolToUint": true,
|
||||
"BoolToFloat": true,
|
||||
"BoolToString": true,
|
||||
"FloatToInt": 42.42,
|
||||
"FloatToUint": 42.42,
|
||||
"FloatToBool": 42.42,
|
||||
"FloatToString": 42.42,
|
||||
"StringToInt": "42",
|
||||
"StringToUint": "42",
|
||||
"StringToBool": "1",
|
||||
"StringToFloat": "42.42",
|
||||
"SliceToMap": []interface{}{},
|
||||
"MapToSlice": map[string]interface{}{},
|
||||
}
|
||||
|
||||
var resultStrict TypeConversionResult
|
||||
for i := 0; i < b.N; i++ {
|
||||
Decode(input, &resultStrict)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_DecodeMap(b *testing.B) {
|
||||
input := map[string]interface{}{
|
||||
"vfoo": "foo",
|
||||
"vother": map[interface{}]interface{}{
|
||||
"foo": "foo",
|
||||
"bar": "bar",
|
||||
},
|
||||
}
|
||||
|
||||
var result Map
|
||||
for i := 0; i < b.N; i++ {
|
||||
Decode(input, &result)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_DecodeMapOfStruct(b *testing.B) {
|
||||
input := map[string]interface{}{
|
||||
"value": map[string]interface{}{
|
||||
"foo": map[string]string{"vstring": "one"},
|
||||
"bar": map[string]string{"vstring": "two"},
|
||||
},
|
||||
}
|
||||
|
||||
var result MapOfStruct
|
||||
for i := 0; i < b.N; i++ {
|
||||
Decode(input, &result)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_DecodeSlice(b *testing.B) {
|
||||
input := map[string]interface{}{
|
||||
"vfoo": "foo",
|
||||
"vbar": []string{"foo", "bar", "baz"},
|
||||
}
|
||||
|
||||
var result Slice
|
||||
for i := 0; i < b.N; i++ {
|
||||
Decode(input, &result)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_DecodeSliceOfStruct(b *testing.B) {
|
||||
input := map[string]interface{}{
|
||||
"value": []map[string]interface{}{
|
||||
{"vstring": "one"},
|
||||
{"vstring": "two"},
|
||||
},
|
||||
}
|
||||
|
||||
var result SliceOfStruct
|
||||
for i := 0; i < b.N; i++ {
|
||||
Decode(input, &result)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_DecodeWeaklyTypedInput(b *testing.B) {
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
Emails []string
|
||||
}
|
||||
|
||||
// This input can come from anywhere, but typically comes from
|
||||
// something like decoding JSON, generated by a weakly typed language
|
||||
// such as PHP.
|
||||
input := map[string]interface{}{
|
||||
"name": 123, // number => string
|
||||
"age": "42", // string => number
|
||||
"emails": map[string]interface{}{}, // empty map => empty array
|
||||
}
|
||||
|
||||
var result Person
|
||||
config := &DecoderConfig{
|
||||
WeaklyTypedInput: true,
|
||||
Result: &result,
|
||||
}
|
||||
|
||||
decoder, err := NewDecoder(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
decoder.Decode(input)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_DecodeMetadata(b *testing.B) {
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
|
||||
input := map[string]interface{}{
|
||||
"name": "Mitchell",
|
||||
"age": 91,
|
||||
"email": "foo@bar.com",
|
||||
}
|
||||
|
||||
var md Metadata
|
||||
var result Person
|
||||
config := &DecoderConfig{
|
||||
Metadata: &md,
|
||||
Result: &result,
|
||||
}
|
||||
|
||||
decoder, err := NewDecoder(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
decoder.Decode(input)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_DecodeMetadataEmbedded(b *testing.B) {
|
||||
input := map[string]interface{}{
|
||||
"vstring": "foo",
|
||||
"vunique": "bar",
|
||||
}
|
||||
|
||||
var md Metadata
|
||||
var result EmbeddedSquash
|
||||
config := &DecoderConfig{
|
||||
Metadata: &md,
|
||||
Result: &result,
|
||||
}
|
||||
|
||||
decoder, err := NewDecoder(config)
|
||||
if err != nil {
|
||||
b.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
decoder.Decode(input)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_DecodeTagged(b *testing.B) {
|
||||
input := map[string]interface{}{
|
||||
"foo": "bar",
|
||||
"bar": "value",
|
||||
}
|
||||
|
||||
var result Tagged
|
||||
for i := 0; i < b.N; i++ {
|
||||
Decode(input, &result)
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
package mapstructure
|
||||
|
||||
import "testing"
|
||||
|
||||
// GH-1
|
||||
func TestDecode_NilValue(t *testing.T) {
|
||||
input := map[string]interface{}{
|
||||
"vfoo": nil,
|
||||
"vother": nil,
|
||||
}
|
||||
|
||||
var result Map
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
t.Fatalf("should not error: %s", err)
|
||||
}
|
||||
|
||||
if result.Vfoo != "" {
|
||||
t.Fatalf("value should be default: %s", result.Vfoo)
|
||||
}
|
||||
|
||||
if result.Vother != nil {
|
||||
t.Fatalf("Vother should be nil: %s", result.Vother)
|
||||
}
|
||||
}
|
||||
|
||||
// GH-10
|
||||
func TestDecode_mapInterfaceInterface(t *testing.T) {
|
||||
input := map[interface{}]interface{}{
|
||||
"vfoo": nil,
|
||||
"vother": nil,
|
||||
}
|
||||
|
||||
var result Map
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
t.Fatalf("should not error: %s", err)
|
||||
}
|
||||
|
||||
if result.Vfoo != "" {
|
||||
t.Fatalf("value should be default: %s", result.Vfoo)
|
||||
}
|
||||
|
||||
if result.Vother != nil {
|
||||
t.Fatalf("Vother should be nil: %s", result.Vother)
|
||||
}
|
||||
}
|
|
@ -1,169 +0,0 @@
|
|||
package mapstructure
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func ExampleDecode() {
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
Emails []string
|
||||
Extra map[string]string
|
||||
}
|
||||
|
||||
// This input can come from anywhere, but typically comes from
|
||||
// something like decoding JSON where we're not quite sure of the
|
||||
// struct initially.
|
||||
input := map[string]interface{}{
|
||||
"name": "Mitchell",
|
||||
"age": 91,
|
||||
"emails": []string{"one", "two", "three"},
|
||||
"extra": map[string]string{
|
||||
"twitter": "mitchellh",
|
||||
},
|
||||
}
|
||||
|
||||
var result Person
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("%#v", result)
|
||||
// Output:
|
||||
// mapstructure.Person{Name:"Mitchell", Age:91, Emails:[]string{"one", "two", "three"}, Extra:map[string]string{"twitter":"mitchellh"}}
|
||||
}
|
||||
|
||||
func ExampleDecode_errors() {
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
Emails []string
|
||||
Extra map[string]string
|
||||
}
|
||||
|
||||
// This input can come from anywhere, but typically comes from
|
||||
// something like decoding JSON where we're not quite sure of the
|
||||
// struct initially.
|
||||
input := map[string]interface{}{
|
||||
"name": 123,
|
||||
"age": "bad value",
|
||||
"emails": []int{1, 2, 3},
|
||||
}
|
||||
|
||||
var result Person
|
||||
err := Decode(input, &result)
|
||||
if err == nil {
|
||||
panic("should have an error")
|
||||
}
|
||||
|
||||
fmt.Println(err.Error())
|
||||
// Output:
|
||||
// 5 error(s) decoding:
|
||||
//
|
||||
// * 'Name' expected type 'string', got unconvertible type 'int'
|
||||
// * 'Age' expected type 'int', got unconvertible type 'string'
|
||||
// * 'Emails[0]' expected type 'string', got unconvertible type 'int'
|
||||
// * 'Emails[1]' expected type 'string', got unconvertible type 'int'
|
||||
// * 'Emails[2]' expected type 'string', got unconvertible type 'int'
|
||||
}
|
||||
|
||||
func ExampleDecode_metadata() {
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
|
||||
// This input can come from anywhere, but typically comes from
|
||||
// something like decoding JSON where we're not quite sure of the
|
||||
// struct initially.
|
||||
input := map[string]interface{}{
|
||||
"name": "Mitchell",
|
||||
"age": 91,
|
||||
"email": "foo@bar.com",
|
||||
}
|
||||
|
||||
// For metadata, we make a more advanced DecoderConfig so we can
|
||||
// more finely configure the decoder that is used. In this case, we
|
||||
// just tell the decoder we want to track metadata.
|
||||
var md Metadata
|
||||
var result Person
|
||||
config := &DecoderConfig{
|
||||
Metadata: &md,
|
||||
Result: &result,
|
||||
}
|
||||
|
||||
decoder, err := NewDecoder(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := decoder.Decode(input); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Unused keys: %#v", md.Unused)
|
||||
// Output:
|
||||
// Unused keys: []string{"email"}
|
||||
}
|
||||
|
||||
func ExampleDecode_weaklyTypedInput() {
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
Emails []string
|
||||
}
|
||||
|
||||
// This input can come from anywhere, but typically comes from
|
||||
// something like decoding JSON, generated by a weakly typed language
|
||||
// such as PHP.
|
||||
input := map[string]interface{}{
|
||||
"name": 123, // number => string
|
||||
"age": "42", // string => number
|
||||
"emails": map[string]interface{}{}, // empty map => empty array
|
||||
}
|
||||
|
||||
var result Person
|
||||
config := &DecoderConfig{
|
||||
WeaklyTypedInput: true,
|
||||
Result: &result,
|
||||
}
|
||||
|
||||
decoder, err := NewDecoder(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = decoder.Decode(input)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("%#v", result)
|
||||
// Output: mapstructure.Person{Name:"123", Age:42, Emails:[]string{}}
|
||||
}
|
||||
|
||||
func ExampleDecode_tags() {
|
||||
// Note that the mapstructure tags defined in the struct type
|
||||
// can indicate which fields the values are mapped to.
|
||||
type Person struct {
|
||||
Name string `mapstructure:"person_name"`
|
||||
Age int `mapstructure:"person_age"`
|
||||
}
|
||||
|
||||
input := map[string]interface{}{
|
||||
"person_name": "Mitchell",
|
||||
"person_age": 91,
|
||||
}
|
||||
|
||||
var result Person
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("%#v", result)
|
||||
// Output:
|
||||
// mapstructure.Person{Name:"Mitchell", Age:91}
|
||||
}
|
|
@ -1,828 +0,0 @@
|
|||
package mapstructure
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type Basic struct {
|
||||
Vstring string
|
||||
Vint int
|
||||
Vuint uint
|
||||
Vbool bool
|
||||
Vfloat float64
|
||||
Vextra string
|
||||
vsilent bool
|
||||
Vdata interface{}
|
||||
}
|
||||
|
||||
type Embedded struct {
|
||||
Basic
|
||||
Vunique string
|
||||
}
|
||||
|
||||
type EmbeddedPointer struct {
|
||||
*Basic
|
||||
Vunique string
|
||||
}
|
||||
|
||||
type EmbeddedSquash struct {
|
||||
Basic `mapstructure:",squash"`
|
||||
Vunique string
|
||||
}
|
||||
|
||||
type Map struct {
|
||||
Vfoo string
|
||||
Vother map[string]string
|
||||
}
|
||||
|
||||
type MapOfStruct struct {
|
||||
Value map[string]Basic
|
||||
}
|
||||
|
||||
type Nested struct {
|
||||
Vfoo string
|
||||
Vbar Basic
|
||||
}
|
||||
|
||||
type NestedPointer struct {
|
||||
Vfoo string
|
||||
Vbar *Basic
|
||||
}
|
||||
|
||||
type Slice struct {
|
||||
Vfoo string
|
||||
Vbar []string
|
||||
}
|
||||
|
||||
type SliceOfStruct struct {
|
||||
Value []Basic
|
||||
}
|
||||
|
||||
type Tagged struct {
|
||||
Extra string `mapstructure:"bar,what,what"`
|
||||
Value string `mapstructure:"foo"`
|
||||
}
|
||||
|
||||
type TypeConversionResult struct {
|
||||
IntToFloat float32
|
||||
IntToUint uint
|
||||
IntToBool bool
|
||||
IntToString string
|
||||
UintToInt int
|
||||
UintToFloat float32
|
||||
UintToBool bool
|
||||
UintToString string
|
||||
BoolToInt int
|
||||
BoolToUint uint
|
||||
BoolToFloat float32
|
||||
BoolToString string
|
||||
FloatToInt int
|
||||
FloatToUint uint
|
||||
FloatToBool bool
|
||||
FloatToString string
|
||||
SliceUint8ToString string
|
||||
StringToInt int
|
||||
StringToUint uint
|
||||
StringToBool bool
|
||||
StringToFloat float32
|
||||
SliceToMap map[string]interface{}
|
||||
MapToSlice []interface{}
|
||||
}
|
||||
|
||||
func TestBasicTypes(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"vstring": "foo",
|
||||
"vint": 42,
|
||||
"Vuint": 42,
|
||||
"vbool": true,
|
||||
"Vfloat": 42.42,
|
||||
"vsilent": true,
|
||||
"vdata": 42,
|
||||
}
|
||||
|
||||
var result Basic
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
t.Errorf("got an err: %s", err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if result.Vstring != "foo" {
|
||||
t.Errorf("vstring value should be 'foo': %#v", result.Vstring)
|
||||
}
|
||||
|
||||
if result.Vint != 42 {
|
||||
t.Errorf("vint value should be 42: %#v", result.Vint)
|
||||
}
|
||||
|
||||
if result.Vuint != 42 {
|
||||
t.Errorf("vuint value should be 42: %#v", result.Vuint)
|
||||
}
|
||||
|
||||
if result.Vbool != true {
|
||||
t.Errorf("vbool value should be true: %#v", result.Vbool)
|
||||
}
|
||||
|
||||
if result.Vfloat != 42.42 {
|
||||
t.Errorf("vfloat value should be 42.42: %#v", result.Vfloat)
|
||||
}
|
||||
|
||||
if result.Vextra != "" {
|
||||
t.Errorf("vextra value should be empty: %#v", result.Vextra)
|
||||
}
|
||||
|
||||
if result.vsilent != false {
|
||||
t.Error("vsilent should not be set, it is unexported")
|
||||
}
|
||||
|
||||
if result.Vdata != 42 {
|
||||
t.Error("vdata should be valid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasic_IntWithFloat(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"vint": float64(42),
|
||||
}
|
||||
|
||||
var result Basic
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
t.Fatalf("got an err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecode_Embedded(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"vstring": "foo",
|
||||
"Basic": map[string]interface{}{
|
||||
"vstring": "innerfoo",
|
||||
},
|
||||
"vunique": "bar",
|
||||
}
|
||||
|
||||
var result Embedded
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
t.Fatalf("got an err: %s", err.Error())
|
||||
}
|
||||
|
||||
if result.Vstring != "innerfoo" {
|
||||
t.Errorf("vstring value should be 'innerfoo': %#v", result.Vstring)
|
||||
}
|
||||
|
||||
if result.Vunique != "bar" {
|
||||
t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecode_EmbeddedPointer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"vstring": "foo",
|
||||
"Basic": map[string]interface{}{
|
||||
"vstring": "innerfoo",
|
||||
},
|
||||
"vunique": "bar",
|
||||
}
|
||||
|
||||
var result EmbeddedPointer
|
||||
err := Decode(input, &result)
|
||||
if err == nil {
|
||||
t.Fatal("should get error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecode_EmbeddedSquash(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"vstring": "foo",
|
||||
"vunique": "bar",
|
||||
}
|
||||
|
||||
var result EmbeddedSquash
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
t.Fatalf("got an err: %s", err.Error())
|
||||
}
|
||||
|
||||
if result.Vstring != "foo" {
|
||||
t.Errorf("vstring value should be 'foo': %#v", result.Vstring)
|
||||
}
|
||||
|
||||
if result.Vunique != "bar" {
|
||||
t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecode_DecodeHook(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"vint": "WHAT",
|
||||
}
|
||||
|
||||
decodeHook := func(from reflect.Kind, to reflect.Kind, v interface{}) (interface{}, error) {
|
||||
if from == reflect.String && to != reflect.String {
|
||||
return 5, nil
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
var result Basic
|
||||
config := &DecoderConfig{
|
||||
DecodeHook: decodeHook,
|
||||
Result: &result,
|
||||
}
|
||||
|
||||
decoder, err := NewDecoder(config)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
err = decoder.Decode(input)
|
||||
if err != nil {
|
||||
t.Fatalf("got an err: %s", err)
|
||||
}
|
||||
|
||||
if result.Vint != 5 {
|
||||
t.Errorf("vint should be 5: %#v", result.Vint)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecode_Nil(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var input interface{} = nil
|
||||
result := Basic{
|
||||
Vstring: "foo",
|
||||
}
|
||||
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if result.Vstring != "foo" {
|
||||
t.Fatalf("bad: %#v", result.Vstring)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecode_NonStruct(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"foo": "bar",
|
||||
"bar": "baz",
|
||||
}
|
||||
|
||||
var result map[string]string
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if result["foo"] != "bar" {
|
||||
t.Fatal("foo is not bar")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecode_TypeConversion(t *testing.T) {
|
||||
input := map[string]interface{}{
|
||||
"IntToFloat": 42,
|
||||
"IntToUint": 42,
|
||||
"IntToBool": 1,
|
||||
"IntToString": 42,
|
||||
"UintToInt": 42,
|
||||
"UintToFloat": 42,
|
||||
"UintToBool": 42,
|
||||
"UintToString": 42,
|
||||
"BoolToInt": true,
|
||||
"BoolToUint": true,
|
||||
"BoolToFloat": true,
|
||||
"BoolToString": true,
|
||||
"FloatToInt": 42.42,
|
||||
"FloatToUint": 42.42,
|
||||
"FloatToBool": 42.42,
|
||||
"FloatToString": 42.42,
|
||||
"SliceUint8ToString": []uint8("foo"),
|
||||
"StringToInt": "42",
|
||||
"StringToUint": "42",
|
||||
"StringToBool": "1",
|
||||
"StringToFloat": "42.42",
|
||||
"SliceToMap": []interface{}{},
|
||||
"MapToSlice": map[string]interface{}{},
|
||||
}
|
||||
|
||||
expectedResultStrict := TypeConversionResult{
|
||||
IntToFloat: 42.0,
|
||||
IntToUint: 42,
|
||||
UintToInt: 42,
|
||||
UintToFloat: 42,
|
||||
BoolToInt: 0,
|
||||
BoolToUint: 0,
|
||||
BoolToFloat: 0,
|
||||
FloatToInt: 42,
|
||||
FloatToUint: 42,
|
||||
}
|
||||
|
||||
expectedResultWeak := TypeConversionResult{
|
||||
IntToFloat: 42.0,
|
||||
IntToUint: 42,
|
||||
IntToBool: true,
|
||||
IntToString: "42",
|
||||
UintToInt: 42,
|
||||
UintToFloat: 42,
|
||||
UintToBool: true,
|
||||
UintToString: "42",
|
||||
BoolToInt: 1,
|
||||
BoolToUint: 1,
|
||||
BoolToFloat: 1,
|
||||
BoolToString: "1",
|
||||
FloatToInt: 42,
|
||||
FloatToUint: 42,
|
||||
FloatToBool: true,
|
||||
FloatToString: "42.42",
|
||||
SliceUint8ToString: "foo",
|
||||
StringToInt: 42,
|
||||
StringToUint: 42,
|
||||
StringToBool: true,
|
||||
StringToFloat: 42.42,
|
||||
SliceToMap: map[string]interface{}{},
|
||||
MapToSlice: []interface{}{},
|
||||
}
|
||||
|
||||
// Test strict type conversion
|
||||
var resultStrict TypeConversionResult
|
||||
err := Decode(input, &resultStrict)
|
||||
if err == nil {
|
||||
t.Errorf("should return an error")
|
||||
}
|
||||
if !reflect.DeepEqual(resultStrict, expectedResultStrict) {
|
||||
t.Errorf("expected %v, got: %v", expectedResultStrict, resultStrict)
|
||||
}
|
||||
|
||||
// Test weak type conversion
|
||||
var decoder *Decoder
|
||||
var resultWeak TypeConversionResult
|
||||
|
||||
config := &DecoderConfig{
|
||||
WeaklyTypedInput: true,
|
||||
Result: &resultWeak,
|
||||
}
|
||||
|
||||
decoder, err = NewDecoder(config)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
err = decoder.Decode(input)
|
||||
if err != nil {
|
||||
t.Fatalf("got an err: %s", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(resultWeak, expectedResultWeak) {
|
||||
t.Errorf("expected \n%#v, got: \n%#v", expectedResultWeak, resultWeak)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecoder_ErrorUnused(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"vstring": "hello",
|
||||
"foo": "bar",
|
||||
}
|
||||
|
||||
var result Basic
|
||||
config := &DecoderConfig{
|
||||
ErrorUnused: true,
|
||||
Result: &result,
|
||||
}
|
||||
|
||||
decoder, err := NewDecoder(config)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
err = decoder.Decode(input)
|
||||
if err == nil {
|
||||
t.Fatal("expected error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMap(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"vfoo": "foo",
|
||||
"vother": map[interface{}]interface{}{
|
||||
"foo": "foo",
|
||||
"bar": "bar",
|
||||
},
|
||||
}
|
||||
|
||||
var result Map
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
t.Fatalf("got an error: %s", err)
|
||||
}
|
||||
|
||||
if result.Vfoo != "foo" {
|
||||
t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
|
||||
}
|
||||
|
||||
if result.Vother == nil {
|
||||
t.Fatal("vother should not be nil")
|
||||
}
|
||||
|
||||
if len(result.Vother) != 2 {
|
||||
t.Error("vother should have two items")
|
||||
}
|
||||
|
||||
if result.Vother["foo"] != "foo" {
|
||||
t.Errorf("'foo' key should be foo, got: %#v", result.Vother["foo"])
|
||||
}
|
||||
|
||||
if result.Vother["bar"] != "bar" {
|
||||
t.Errorf("'bar' key should be bar, got: %#v", result.Vother["bar"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapOfStruct(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"value": map[string]interface{}{
|
||||
"foo": map[string]string{"vstring": "one"},
|
||||
"bar": map[string]string{"vstring": "two"},
|
||||
},
|
||||
}
|
||||
|
||||
var result MapOfStruct
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
t.Fatalf("got an err: %s", err)
|
||||
}
|
||||
|
||||
if result.Value == nil {
|
||||
t.Fatal("value should not be nil")
|
||||
}
|
||||
|
||||
if len(result.Value) != 2 {
|
||||
t.Error("value should have two items")
|
||||
}
|
||||
|
||||
if result.Value["foo"].Vstring != "one" {
|
||||
t.Errorf("foo value should be 'one', got: %s", result.Value["foo"].Vstring)
|
||||
}
|
||||
|
||||
if result.Value["bar"].Vstring != "two" {
|
||||
t.Errorf("bar value should be 'two', got: %s", result.Value["bar"].Vstring)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNestedType(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"vfoo": "foo",
|
||||
"vbar": map[string]interface{}{
|
||||
"vstring": "foo",
|
||||
"vint": 42,
|
||||
"vbool": true,
|
||||
},
|
||||
}
|
||||
|
||||
var result Nested
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
t.Fatalf("got an err: %s", err.Error())
|
||||
}
|
||||
|
||||
if result.Vfoo != "foo" {
|
||||
t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
|
||||
}
|
||||
|
||||
if result.Vbar.Vstring != "foo" {
|
||||
t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
|
||||
}
|
||||
|
||||
if result.Vbar.Vint != 42 {
|
||||
t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
|
||||
}
|
||||
|
||||
if result.Vbar.Vbool != true {
|
||||
t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
|
||||
}
|
||||
|
||||
if result.Vbar.Vextra != "" {
|
||||
t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNestedTypePointer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"vfoo": "foo",
|
||||
"vbar": &map[string]interface{}{
|
||||
"vstring": "foo",
|
||||
"vint": 42,
|
||||
"vbool": true,
|
||||
},
|
||||
}
|
||||
|
||||
var result NestedPointer
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
t.Fatalf("got an err: %s", err.Error())
|
||||
}
|
||||
|
||||
if result.Vfoo != "foo" {
|
||||
t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
|
||||
}
|
||||
|
||||
if result.Vbar.Vstring != "foo" {
|
||||
t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
|
||||
}
|
||||
|
||||
if result.Vbar.Vint != 42 {
|
||||
t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
|
||||
}
|
||||
|
||||
if result.Vbar.Vbool != true {
|
||||
t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
|
||||
}
|
||||
|
||||
if result.Vbar.Vextra != "" {
|
||||
t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlice(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
inputStringSlice := map[string]interface{}{
|
||||
"vfoo": "foo",
|
||||
"vbar": []string{"foo", "bar", "baz"},
|
||||
}
|
||||
|
||||
inputStringSlicePointer := map[string]interface{}{
|
||||
"vfoo": "foo",
|
||||
"vbar": &[]string{"foo", "bar", "baz"},
|
||||
}
|
||||
|
||||
outputStringSlice := &Slice{
|
||||
"foo",
|
||||
[]string{"foo", "bar", "baz"},
|
||||
}
|
||||
|
||||
testSliceInput(t, inputStringSlice, outputStringSlice)
|
||||
testSliceInput(t, inputStringSlicePointer, outputStringSlice)
|
||||
}
|
||||
|
||||
func TestInvalidSlice(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"vfoo": "foo",
|
||||
"vbar": 42,
|
||||
}
|
||||
|
||||
result := Slice{}
|
||||
err := Decode(input, &result)
|
||||
if err == nil {
|
||||
t.Errorf("expected failure")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSliceOfStruct(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"value": []map[string]interface{}{
|
||||
{"vstring": "one"},
|
||||
{"vstring": "two"},
|
||||
},
|
||||
}
|
||||
|
||||
var result SliceOfStruct
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
t.Fatalf("got unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if len(result.Value) != 2 {
|
||||
t.Fatalf("expected two values, got %d", len(result.Value))
|
||||
}
|
||||
|
||||
if result.Value[0].Vstring != "one" {
|
||||
t.Errorf("first value should be 'one', got: %s", result.Value[0].Vstring)
|
||||
}
|
||||
|
||||
if result.Value[1].Vstring != "two" {
|
||||
t.Errorf("second value should be 'two', got: %s", result.Value[1].Vstring)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidType(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"vstring": 42,
|
||||
}
|
||||
|
||||
var result Basic
|
||||
err := Decode(input, &result)
|
||||
if err == nil {
|
||||
t.Fatal("error should exist")
|
||||
}
|
||||
|
||||
derr, ok := err.(*Error)
|
||||
if !ok {
|
||||
t.Fatalf("error should be kind of Error, instead: %#v", err)
|
||||
}
|
||||
|
||||
if derr.Errors[0] != "'Vstring' expected type 'string', got unconvertible type 'int'" {
|
||||
t.Errorf("got unexpected error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetadata(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"vfoo": "foo",
|
||||
"vbar": map[string]interface{}{
|
||||
"vstring": "foo",
|
||||
"Vuint": 42,
|
||||
"foo": "bar",
|
||||
},
|
||||
"bar": "nil",
|
||||
}
|
||||
|
||||
var md Metadata
|
||||
var result Nested
|
||||
config := &DecoderConfig{
|
||||
Metadata: &md,
|
||||
Result: &result,
|
||||
}
|
||||
|
||||
decoder, err := NewDecoder(config)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
err = decoder.Decode(input)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err.Error())
|
||||
}
|
||||
|
||||
expectedKeys := []string{"Vfoo", "Vbar.Vstring", "Vbar.Vuint", "Vbar"}
|
||||
if !reflect.DeepEqual(md.Keys, expectedKeys) {
|
||||
t.Fatalf("bad keys: %#v", md.Keys)
|
||||
}
|
||||
|
||||
expectedUnused := []string{"Vbar.foo", "bar"}
|
||||
if !reflect.DeepEqual(md.Unused, expectedUnused) {
|
||||
t.Fatalf("bad unused: %#v", md.Unused)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetadata_Embedded(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"vstring": "foo",
|
||||
"vunique": "bar",
|
||||
}
|
||||
|
||||
var md Metadata
|
||||
var result EmbeddedSquash
|
||||
config := &DecoderConfig{
|
||||
Metadata: &md,
|
||||
Result: &result,
|
||||
}
|
||||
|
||||
decoder, err := NewDecoder(config)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
err = decoder.Decode(input)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err.Error())
|
||||
}
|
||||
|
||||
expectedKeys := []string{"Vstring", "Vunique"}
|
||||
|
||||
sort.Strings(md.Keys)
|
||||
if !reflect.DeepEqual(md.Keys, expectedKeys) {
|
||||
t.Fatalf("bad keys: %#v", md.Keys)
|
||||
}
|
||||
|
||||
expectedUnused := []string{}
|
||||
if !reflect.DeepEqual(md.Unused, expectedUnused) {
|
||||
t.Fatalf("bad unused: %#v", md.Unused)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNonPtrValue(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
err := Decode(map[string]interface{}{}, Basic{})
|
||||
if err == nil {
|
||||
t.Fatal("error should exist")
|
||||
}
|
||||
|
||||
if err.Error() != "result must be a pointer" {
|
||||
t.Errorf("got unexpected error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTagged(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"foo": "bar",
|
||||
"bar": "value",
|
||||
}
|
||||
|
||||
var result Tagged
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if result.Value != "bar" {
|
||||
t.Errorf("value should be 'bar', got: %#v", result.Value)
|
||||
}
|
||||
|
||||
if result.Extra != "value" {
|
||||
t.Errorf("extra should be 'value', got: %#v", result.Extra)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWeakDecode(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
input := map[string]interface{}{
|
||||
"foo": "4",
|
||||
"bar": "value",
|
||||
}
|
||||
|
||||
var result struct {
|
||||
Foo int
|
||||
Bar string
|
||||
}
|
||||
|
||||
if err := WeakDecode(input, &result); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if result.Foo != 4 {
|
||||
t.Fatalf("bad: %#v", result)
|
||||
}
|
||||
if result.Bar != "value" {
|
||||
t.Fatalf("bad: %#v", result)
|
||||
}
|
||||
}
|
||||
|
||||
func testSliceInput(t *testing.T, input map[string]interface{}, expected *Slice) {
|
||||
var result Slice
|
||||
err := Decode(input, &result)
|
||||
if err != nil {
|
||||
t.Fatalf("got error: %s", err)
|
||||
}
|
||||
|
||||
if result.Vfoo != expected.Vfoo {
|
||||
t.Errorf("Vfoo expected '%s', got '%s'", expected.Vfoo, result.Vfoo)
|
||||
}
|
||||
|
||||
if result.Vbar == nil {
|
||||
t.Fatalf("Vbar a slice, got '%#v'", result.Vbar)
|
||||
}
|
||||
|
||||
if len(result.Vbar) != len(expected.Vbar) {
|
||||
t.Errorf("Vbar length should be %d, got %d", len(expected.Vbar), len(result.Vbar))
|
||||
}
|
||||
|
||||
for i, v := range result.Vbar {
|
||||
if v != expected.Vbar[i] {
|
||||
t.Errorf(
|
||||
"Vbar[%d] should be '%#v', got '%#v'",
|
||||
i, expected.Vbar[i], v)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2014 exoscale(tm)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -1,70 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots"
|
||||
"github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestSnapshots(t *testing.T) {
|
||||
|
||||
client, err := newClient(t)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
v, err := volumes.Create(client, &volumes.CreateOpts{
|
||||
Name: "gophercloud-test-volume",
|
||||
Size: 1,
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
err = volumes.WaitForStatus(client, v.ID, "available", 120)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Created volume: %v\n", v)
|
||||
|
||||
ss, err := snapshots.Create(client, &snapshots.CreateOpts{
|
||||
Name: "gophercloud-test-snapshot",
|
||||
VolumeID: v.ID,
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
err = snapshots.WaitForStatus(client, ss.ID, "available", 120)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Created snapshot: %+v\n", ss)
|
||||
|
||||
err = snapshots.Delete(client, ss.ID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
err = gophercloud.WaitFor(120, func() (bool, error) {
|
||||
_, err := snapshots.Get(client, ss.ID).Extract()
|
||||
if err != nil {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Log("Deleted snapshot\n")
|
||||
|
||||
err = volumes.Delete(client, v.ID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
err = gophercloud.WaitFor(120, func() (bool, error) {
|
||||
_, err := volumes.Get(client, v.ID).Extract()
|
||||
if err != nil {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Log("Deleted volume\n")
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
// +build acceptance blockstorage
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack"
|
||||
"github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func newClient(t *testing.T) (*gophercloud.ServiceClient, error) {
|
||||
ao, err := openstack.AuthOptionsFromEnv()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
client, err := openstack.AuthenticatedClient(ao)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
return openstack.NewBlockStorageV1(client, gophercloud.EndpointOpts{
|
||||
Region: os.Getenv("OS_REGION_NAME"),
|
||||
})
|
||||
}
|
||||
|
||||
func TestVolumes(t *testing.T) {
|
||||
client, err := newClient(t)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
cv, err := volumes.Create(client, &volumes.CreateOpts{
|
||||
Size: 1,
|
||||
Name: "gophercloud-test-volume",
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
defer func() {
|
||||
err = volumes.WaitForStatus(client, cv.ID, "available", 60)
|
||||
th.AssertNoErr(t, err)
|
||||
err = volumes.Delete(client, cv.ID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
}()
|
||||
|
||||
_, err = volumes.Update(client, cv.ID, &volumes.UpdateOpts{
|
||||
Name: "gophercloud-updated-volume",
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
v, err := volumes.Get(client, cv.ID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Got volume: %+v\n", v)
|
||||
|
||||
if v.Name != "gophercloud-updated-volume" {
|
||||
t.Errorf("Unable to update volume: Expected name: gophercloud-updated-volume\nActual name: %s", v.Name)
|
||||
}
|
||||
|
||||
err = volumes.List(client, &volumes.ListOpts{Name: "gophercloud-updated-volume"}).EachPage(func(page pagination.Page) (bool, error) {
|
||||
vols, err := volumes.ExtractVolumes(page)
|
||||
th.CheckEquals(t, 1, len(vols))
|
||||
return true, err
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestVolumeTypes(t *testing.T) {
|
||||
client, err := newClient(t)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
vt, err := volumetypes.Create(client, &volumetypes.CreateOpts{
|
||||
ExtraSpecs: map[string]interface{}{
|
||||
"capabilities": "gpu",
|
||||
"priority": 3,
|
||||
},
|
||||
Name: "gophercloud-test-volumeType",
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
defer func() {
|
||||
time.Sleep(10000 * time.Millisecond)
|
||||
err = volumetypes.Delete(client, vt.ID).ExtractErr()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
t.Logf("Created volume type: %+v\n", vt)
|
||||
|
||||
vt, err = volumetypes.Get(client, vt.ID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Got volume type: %+v\n", vt)
|
||||
|
||||
err = volumetypes.List(client).EachPage(func(page pagination.Page) (bool, error) {
|
||||
volTypes, err := volumetypes.ExtractVolumeTypes(page)
|
||||
if len(volTypes) != 1 {
|
||||
t.Errorf("Expected 1 volume type, got %d", len(volTypes))
|
||||
}
|
||||
t.Logf("Listing volume types: %+v\n", volTypes)
|
||||
return true, err
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package openstack
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack"
|
||||
)
|
||||
|
||||
func TestAuthenticatedClient(t *testing.T) {
|
||||
// Obtain credentials from the environment.
|
||||
ao, err := openstack.AuthOptionsFromEnv()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to acquire credentials: %v", err)
|
||||
}
|
||||
|
||||
client, err := openstack.AuthenticatedClient(ao)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to authenticate: %v", err)
|
||||
}
|
||||
|
||||
if client.TokenID == "" {
|
||||
t.Errorf("No token ID assigned to the client")
|
||||
}
|
||||
|
||||
t.Logf("Client successfully acquired a token: %v", client.TokenID)
|
||||
|
||||
// Find the storage service in the service catalog.
|
||||
storage, err := openstack.NewObjectStorageV1(client, gophercloud.EndpointOpts{
|
||||
Region: os.Getenv("OS_REGION_NAME"),
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("Unable to locate a storage service: %v", err)
|
||||
} else {
|
||||
t.Logf("Located a storage service at endpoint: [%s]", storage.Endpoint)
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestBootFromVolume(t *testing.T) {
|
||||
client, err := newClient()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping test that requires server creation in short mode.")
|
||||
}
|
||||
|
||||
choices, err := ComputeChoicesFromEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
name := tools.RandomString("Gophercloud-", 8)
|
||||
t.Logf("Creating server [%s].", name)
|
||||
|
||||
bd := []bootfromvolume.BlockDevice{
|
||||
bootfromvolume.BlockDevice{
|
||||
UUID: choices.ImageID,
|
||||
SourceType: bootfromvolume.Image,
|
||||
VolumeSize: 10,
|
||||
},
|
||||
}
|
||||
|
||||
serverCreateOpts := servers.CreateOpts{
|
||||
Name: name,
|
||||
FlavorRef: choices.FlavorID,
|
||||
ImageRef: choices.ImageID,
|
||||
}
|
||||
server, err := bootfromvolume.Create(client, bootfromvolume.CreateOptsExt{
|
||||
serverCreateOpts,
|
||||
bd,
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Logf("Created server: %+v\n", server)
|
||||
defer servers.Delete(client, server.ID)
|
||||
t.Logf("Deleting server [%s]...", name)
|
||||
}
|
104
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/compute_test.go
generated
vendored
104
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/compute_test.go
generated
vendored
|
@ -1,104 +0,0 @@
|
|||
// +build acceptance common
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||
"github.com/rackspace/gophercloud/openstack"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
)
|
||||
|
||||
func newClient() (*gophercloud.ServiceClient, error) {
|
||||
ao, err := openstack.AuthOptionsFromEnv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client, err := openstack.AuthenticatedClient(ao)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return openstack.NewComputeV2(client, gophercloud.EndpointOpts{
|
||||
Region: os.Getenv("OS_REGION_NAME"),
|
||||
})
|
||||
}
|
||||
|
||||
func waitForStatus(client *gophercloud.ServiceClient, server *servers.Server, status string) error {
|
||||
return tools.WaitFor(func() (bool, error) {
|
||||
latest, err := servers.Get(client, server.ID).Extract()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if latest.Status == status {
|
||||
// Success!
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
})
|
||||
}
|
||||
|
||||
// ComputeChoices contains image and flavor selections for use by the acceptance tests.
|
||||
type ComputeChoices struct {
|
||||
// ImageID contains the ID of a valid image.
|
||||
ImageID string
|
||||
|
||||
// FlavorID contains the ID of a valid flavor.
|
||||
FlavorID string
|
||||
|
||||
// FlavorIDResize contains the ID of a different flavor available on the same OpenStack installation, that is distinct
|
||||
// from FlavorID.
|
||||
FlavorIDResize string
|
||||
|
||||
// NetworkName is the name of a network to launch the instance on.
|
||||
NetworkName string
|
||||
}
|
||||
|
||||
// ComputeChoicesFromEnv populates a ComputeChoices struct from environment variables.
|
||||
// If any required state is missing, an `error` will be returned that enumerates the missing properties.
|
||||
func ComputeChoicesFromEnv() (*ComputeChoices, error) {
|
||||
imageID := os.Getenv("OS_IMAGE_ID")
|
||||
flavorID := os.Getenv("OS_FLAVOR_ID")
|
||||
flavorIDResize := os.Getenv("OS_FLAVOR_ID_RESIZE")
|
||||
networkName := os.Getenv("OS_NETWORK_NAME")
|
||||
|
||||
missing := make([]string, 0, 3)
|
||||
if imageID == "" {
|
||||
missing = append(missing, "OS_IMAGE_ID")
|
||||
}
|
||||
if flavorID == "" {
|
||||
missing = append(missing, "OS_FLAVOR_ID")
|
||||
}
|
||||
if flavorIDResize == "" {
|
||||
missing = append(missing, "OS_FLAVOR_ID_RESIZE")
|
||||
}
|
||||
if networkName == "" {
|
||||
networkName = "public"
|
||||
}
|
||||
|
||||
notDistinct := ""
|
||||
if flavorID == flavorIDResize {
|
||||
notDistinct = "OS_FLAVOR_ID and OS_FLAVOR_ID_RESIZE must be distinct."
|
||||
}
|
||||
|
||||
if len(missing) > 0 || notDistinct != "" {
|
||||
text := "You're missing some important setup:\n"
|
||||
if len(missing) > 0 {
|
||||
text += " * These environment variables must be provided: " + strings.Join(missing, ", ") + "\n"
|
||||
}
|
||||
if notDistinct != "" {
|
||||
text += " * " + notDistinct + "\n"
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf(text)
|
||||
}
|
||||
|
||||
return &ComputeChoices{ImageID: imageID, FlavorID: flavorID, FlavorIDResize: flavorIDResize, NetworkName: networkName}, nil
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
// +build acceptance compute extensionss
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestListExtensions(t *testing.T) {
|
||||
client, err := newClient()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
err = extensions.List(client).EachPage(func(page pagination.Page) (bool, error) {
|
||||
t.Logf("--- Page ---")
|
||||
|
||||
exts, err := extensions.ExtractExtensions(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for i, ext := range exts {
|
||||
t.Logf("[%02d] name=[%s]\n", i, ext.Name)
|
||||
t.Logf(" alias=[%s]\n", ext.Alias)
|
||||
t.Logf(" description=[%s]\n", ext.Description)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func TestGetExtension(t *testing.T) {
|
||||
client, err := newClient()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
ext, err := extensions.Get(client, "os-admin-actions").Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Extension details:")
|
||||
t.Logf(" name=[%s]\n", ext.Name)
|
||||
t.Logf(" namespace=[%s]\n", ext.Namespace)
|
||||
t.Logf(" alias=[%s]\n", ext.Alias)
|
||||
t.Logf(" description=[%s]\n", ext.Description)
|
||||
t.Logf(" updated=[%s]\n", ext.Updated)
|
||||
}
|
57
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/flavors_test.go
generated
vendored
57
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/flavors_test.go
generated
vendored
|
@ -1,57 +0,0 @@
|
|||
// +build acceptance compute flavors
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/flavors"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
func TestListFlavors(t *testing.T) {
|
||||
client, err := newClient()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a compute client: %v", err)
|
||||
}
|
||||
|
||||
t.Logf("ID\tRegion\tName\tStatus\tCreated")
|
||||
|
||||
pager := flavors.ListDetail(client, nil)
|
||||
count, pages := 0, 0
|
||||
pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
t.Logf("---")
|
||||
pages++
|
||||
flavors, err := flavors.ExtractFlavors(page)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, f := range flavors {
|
||||
t.Logf("%s\t%s\t%d\t%d\t%d", f.ID, f.Name, f.RAM, f.Disk, f.VCPUs)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
t.Logf("--------\n%d flavors listed on %d pages.", count, pages)
|
||||
}
|
||||
|
||||
func TestGetFlavor(t *testing.T) {
|
||||
client, err := newClient()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a compute client: %v", err)
|
||||
}
|
||||
|
||||
choices, err := ComputeChoicesFromEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
flavor, err := flavors.Get(client, choices.FlavorID).Extract()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to get flavor information: %v", err)
|
||||
}
|
||||
|
||||
t.Logf("Flavor: %#v", flavor)
|
||||
}
|
107
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/floatingip_test.go
generated
vendored
107
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/floatingip_test.go
generated
vendored
|
@ -1,107 +0,0 @@
|
|||
// +build acceptance compute servers
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func createFIPServer(t *testing.T, client *gophercloud.ServiceClient, choices *ComputeChoices) (*servers.Server, error) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping test that requires server creation in short mode.")
|
||||
}
|
||||
|
||||
name := tools.RandomString("ACPTTEST", 16)
|
||||
t.Logf("Attempting to create server: %s\n", name)
|
||||
|
||||
pwd := tools.MakeNewPassword("")
|
||||
|
||||
server, err := servers.Create(client, servers.CreateOpts{
|
||||
Name: name,
|
||||
FlavorRef: choices.FlavorID,
|
||||
ImageRef: choices.ImageID,
|
||||
AdminPass: pwd,
|
||||
}).Extract()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create server: %v", err)
|
||||
}
|
||||
|
||||
th.AssertEquals(t, pwd, server.AdminPass)
|
||||
|
||||
return server, err
|
||||
}
|
||||
|
||||
func createFloatingIP(t *testing.T, client *gophercloud.ServiceClient) (*floatingip.FloatingIP, error) {
|
||||
pool := os.Getenv("OS_POOL_NAME")
|
||||
fip, err := floatingip.Create(client, &floatingip.CreateOpts{
|
||||
Pool: pool,
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Obtained Floating IP: %v", fip.IP)
|
||||
|
||||
return fip, err
|
||||
}
|
||||
|
||||
func associateFloatingIP(t *testing.T, client *gophercloud.ServiceClient, serverId string, fip *floatingip.FloatingIP) {
|
||||
err := floatingip.Associate(client, serverId, fip.IP).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Associated floating IP %v from instance %v", fip.IP, serverId)
|
||||
defer func() {
|
||||
err = floatingip.Disassociate(client, serverId, fip.IP).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Disassociated floating IP %v from instance %v", fip.IP, serverId)
|
||||
}()
|
||||
floatingIp, err := floatingip.Get(client, fip.ID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Floating IP %v is associated with Fixed IP %v", fip.IP, floatingIp.FixedIP)
|
||||
}
|
||||
|
||||
func TestFloatingIP(t *testing.T) {
|
||||
pool := os.Getenv("OS_POOL_NAME")
|
||||
if pool == "" {
|
||||
t.Fatalf("OS_POOL_NAME must be set")
|
||||
}
|
||||
|
||||
choices, err := ComputeChoicesFromEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
client, err := newClient()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a compute client: %v", err)
|
||||
}
|
||||
|
||||
server, err := createFIPServer(t, client, choices)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create server: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
servers.Delete(client, server.ID)
|
||||
t.Logf("Server deleted.")
|
||||
}()
|
||||
|
||||
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
|
||||
t.Fatalf("Unable to wait for server: %v", err)
|
||||
}
|
||||
|
||||
fip, err := createFloatingIP(t, client)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create floating IP: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
err = floatingip.Delete(client, fip.ID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Floating IP deleted.")
|
||||
}()
|
||||
|
||||
associateFloatingIP(t, client, server.ID, fip)
|
||||
|
||||
}
|
37
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/images_test.go
generated
vendored
37
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/images_test.go
generated
vendored
|
@ -1,37 +0,0 @@
|
|||
// +build acceptance compute images
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/images"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
func TestListImages(t *testing.T) {
|
||||
client, err := newClient()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a compute: client: %v", err)
|
||||
}
|
||||
|
||||
t.Logf("ID\tRegion\tName\tStatus\tCreated")
|
||||
|
||||
pager := images.ListDetail(client, nil)
|
||||
count, pages := 0, 0
|
||||
pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
pages++
|
||||
images, err := images.ExtractImages(page)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, i := range images {
|
||||
t.Logf("%s\t%s\t%s\t%s", i.ID, i.Name, i.Status, i.Created)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
t.Logf("--------\n%d images listed on %d pages.", count, pages)
|
||||
}
|
74
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/keypairs_test.go
generated
vendored
74
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/keypairs_test.go
generated
vendored
|
@ -1,74 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
|
||||
"code.google.com/p/go.crypto/ssh"
|
||||
)
|
||||
|
||||
const keyName = "gophercloud_test_key_pair"
|
||||
|
||||
func TestCreateServerWithKeyPair(t *testing.T) {
|
||||
client, err := newClient()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping test that requires server creation in short mode.")
|
||||
}
|
||||
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
publicKey := privateKey.PublicKey
|
||||
pub, err := ssh.NewPublicKey(&publicKey)
|
||||
th.AssertNoErr(t, err)
|
||||
pubBytes := ssh.MarshalAuthorizedKey(pub)
|
||||
pk := string(pubBytes)
|
||||
|
||||
kp, err := keypairs.Create(client, keypairs.CreateOpts{
|
||||
Name: keyName,
|
||||
PublicKey: pk,
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Created key pair: %s\n", kp)
|
||||
|
||||
choices, err := ComputeChoicesFromEnv()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
name := tools.RandomString("Gophercloud-", 8)
|
||||
t.Logf("Creating server [%s] with key pair.", name)
|
||||
|
||||
serverCreateOpts := servers.CreateOpts{
|
||||
Name: name,
|
||||
FlavorRef: choices.FlavorID,
|
||||
ImageRef: choices.ImageID,
|
||||
}
|
||||
|
||||
server, err := servers.Create(client, keypairs.CreateOptsExt{
|
||||
serverCreateOpts,
|
||||
keyName,
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
defer servers.Delete(client, server.ID)
|
||||
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
|
||||
t.Fatalf("Unable to wait for server: %v", err)
|
||||
}
|
||||
|
||||
server, err = servers.Get(client, server.ID).Extract()
|
||||
t.Logf("Created server: %+v\n", server)
|
||||
th.AssertNoErr(t, err)
|
||||
th.AssertEquals(t, server.KeyName, keyName)
|
||||
|
||||
t.Logf("Deleting key pair [%s]...", kp.Name)
|
||||
err = keypairs.Delete(client, keyName).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Deleting server [%s]...", name)
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
// +build acceptance compute defsecrules
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||
dsr "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestSecDefRules(t *testing.T) {
|
||||
client, err := newClient()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
id := createDefRule(t, client)
|
||||
|
||||
listDefRules(t, client)
|
||||
|
||||
getDefRule(t, client, id)
|
||||
|
||||
deleteDefRule(t, client, id)
|
||||
}
|
||||
|
||||
func createDefRule(t *testing.T, client *gophercloud.ServiceClient) string {
|
||||
opts := dsr.CreateOpts{
|
||||
FromPort: tools.RandomInt(80, 89),
|
||||
ToPort: tools.RandomInt(90, 99),
|
||||
IPProtocol: "TCP",
|
||||
CIDR: "0.0.0.0/0",
|
||||
}
|
||||
|
||||
rule, err := dsr.Create(client, opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Created default rule %s", rule.ID)
|
||||
|
||||
return rule.ID
|
||||
}
|
||||
|
||||
func listDefRules(t *testing.T, client *gophercloud.ServiceClient) {
|
||||
err := dsr.List(client).EachPage(func(page pagination.Page) (bool, error) {
|
||||
drList, err := dsr.ExtractDefaultRules(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, dr := range drList {
|
||||
t.Logf("Listing default rule %s: Name [%s] From Port [%s] To Port [%s] Protocol [%s]",
|
||||
dr.ID, dr.FromPort, dr.ToPort, dr.IPProtocol)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func getDefRule(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||
rule, err := dsr.Get(client, id).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Getting rule %s: %#v", id, rule)
|
||||
}
|
||||
|
||||
func deleteDefRule(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||
err := dsr.Delete(client, id).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Deleted rule %s", id)
|
||||
}
|
177
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/secgroup_test.go
generated
vendored
177
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/secgroup_test.go
generated
vendored
|
@ -1,177 +0,0 @@
|
|||
// +build acceptance compute secgroups
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestSecGroups(t *testing.T) {
|
||||
client, err := newClient()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
serverID, needsDeletion := findServer(t, client)
|
||||
|
||||
groupID := createSecGroup(t, client)
|
||||
|
||||
listSecGroups(t, client)
|
||||
|
||||
newName := tools.RandomString("secgroup_", 5)
|
||||
updateSecGroup(t, client, groupID, newName)
|
||||
|
||||
getSecGroup(t, client, groupID)
|
||||
|
||||
addRemoveRules(t, client, groupID)
|
||||
|
||||
addServerToSecGroup(t, client, serverID, newName)
|
||||
|
||||
removeServerFromSecGroup(t, client, serverID, newName)
|
||||
|
||||
if needsDeletion {
|
||||
servers.Delete(client, serverID)
|
||||
}
|
||||
|
||||
deleteSecGroup(t, client, groupID)
|
||||
}
|
||||
|
||||
func createSecGroup(t *testing.T, client *gophercloud.ServiceClient) string {
|
||||
opts := secgroups.CreateOpts{
|
||||
Name: tools.RandomString("secgroup_", 5),
|
||||
Description: "something",
|
||||
}
|
||||
|
||||
group, err := secgroups.Create(client, opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Created secgroup %s %s", group.ID, group.Name)
|
||||
|
||||
return group.ID
|
||||
}
|
||||
|
||||
func listSecGroups(t *testing.T, client *gophercloud.ServiceClient) {
|
||||
err := secgroups.List(client).EachPage(func(page pagination.Page) (bool, error) {
|
||||
secGrpList, err := secgroups.ExtractSecurityGroups(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, sg := range secGrpList {
|
||||
t.Logf("Listing secgroup %s: Name [%s] Desc [%s] TenantID [%s]", sg.ID,
|
||||
sg.Name, sg.Description, sg.TenantID)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func updateSecGroup(t *testing.T, client *gophercloud.ServiceClient, id, newName string) {
|
||||
opts := secgroups.UpdateOpts{
|
||||
Name: newName,
|
||||
Description: tools.RandomString("dec_", 10),
|
||||
}
|
||||
group, err := secgroups.Update(client, id, opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Updated %s's name to %s", group.ID, group.Name)
|
||||
}
|
||||
|
||||
func getSecGroup(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||
group, err := secgroups.Get(client, id).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Getting %s: %#v", id, group)
|
||||
}
|
||||
|
||||
func addRemoveRules(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||
opts := secgroups.CreateRuleOpts{
|
||||
ParentGroupID: id,
|
||||
FromPort: 22,
|
||||
ToPort: 22,
|
||||
IPProtocol: "TCP",
|
||||
CIDR: "0.0.0.0/0",
|
||||
}
|
||||
|
||||
rule, err := secgroups.CreateRule(client, opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Adding rule %s to group %s", rule.ID, id)
|
||||
|
||||
err = secgroups.DeleteRule(client, rule.ID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Deleted rule %s from group %s", rule.ID, id)
|
||||
}
|
||||
|
||||
func findServer(t *testing.T, client *gophercloud.ServiceClient) (string, bool) {
|
||||
var serverID string
|
||||
var needsDeletion bool
|
||||
|
||||
err := servers.List(client, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||
sList, err := servers.ExtractServers(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, s := range sList {
|
||||
serverID = s.ID
|
||||
needsDeletion = false
|
||||
|
||||
t.Logf("Found an existing server: ID [%s]", serverID)
|
||||
break
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
if serverID == "" {
|
||||
t.Log("No server found, creating one")
|
||||
|
||||
choices, err := ComputeChoicesFromEnv()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
opts := &servers.CreateOpts{
|
||||
Name: tools.RandomString("secgroup_test_", 5),
|
||||
ImageRef: choices.ImageID,
|
||||
FlavorRef: choices.FlavorID,
|
||||
}
|
||||
|
||||
s, err := servers.Create(client, opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
serverID = s.ID
|
||||
|
||||
t.Logf("Created server %s, waiting for it to build", s.ID)
|
||||
err = servers.WaitForStatus(client, serverID, "ACTIVE", 300)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
needsDeletion = true
|
||||
}
|
||||
|
||||
return serverID, needsDeletion
|
||||
}
|
||||
|
||||
func addServerToSecGroup(t *testing.T, client *gophercloud.ServiceClient, serverID, groupName string) {
|
||||
err := secgroups.AddServerToGroup(client, serverID, groupName).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Adding group %s to server %s", groupName, serverID)
|
||||
}
|
||||
|
||||
func removeServerFromSecGroup(t *testing.T, client *gophercloud.ServiceClient, serverID, groupName string) {
|
||||
err := secgroups.RemoveServerFromGroup(client, serverID, groupName).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Removing group %s from server %s", groupName, serverID)
|
||||
}
|
||||
|
||||
func deleteSecGroup(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||
err := secgroups.Delete(client, id).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Deleted group %s", id)
|
||||
}
|
478
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/servers_test.go
generated
vendored
478
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/servers_test.go
generated
vendored
|
@ -1,478 +0,0 @@
|
|||
// +build acceptance compute servers
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||
"github.com/rackspace/gophercloud/openstack"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestListServers(t *testing.T) {
|
||||
client, err := newClient()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a compute client: %v", err)
|
||||
}
|
||||
|
||||
t.Logf("ID\tRegion\tName\tStatus\tIPv4\tIPv6")
|
||||
|
||||
pager := servers.List(client, servers.ListOpts{})
|
||||
count, pages := 0, 0
|
||||
pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
pages++
|
||||
t.Logf("---")
|
||||
|
||||
servers, err := servers.ExtractServers(page)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, s := range servers {
|
||||
t.Logf("%s\t%s\t%s\t%s\t%s\t\n", s.ID, s.Name, s.Status, s.AccessIPv4, s.AccessIPv6)
|
||||
count++
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
t.Logf("--------\n%d servers listed on %d pages.\n", count, pages)
|
||||
}
|
||||
|
||||
func networkingClient() (*gophercloud.ServiceClient, error) {
|
||||
opts, err := openstack.AuthOptionsFromEnv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
provider, err := openstack.AuthenticatedClient(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{
|
||||
Region: os.Getenv("OS_REGION_NAME"),
|
||||
})
|
||||
}
|
||||
|
||||
func createServer(t *testing.T, client *gophercloud.ServiceClient, choices *ComputeChoices) (*servers.Server, error) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping test that requires server creation in short mode.")
|
||||
}
|
||||
|
||||
var network networks.Network
|
||||
|
||||
networkingClient, err := networkingClient()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a networking client: %v", err)
|
||||
}
|
||||
|
||||
pager := networks.List(networkingClient, networks.ListOpts{
|
||||
Name: choices.NetworkName,
|
||||
Limit: 1,
|
||||
})
|
||||
pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
networks, err := networks.ExtractNetworks(page)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to extract networks: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
if len(networks) == 0 {
|
||||
t.Fatalf("No networks to attach to server")
|
||||
return false, err
|
||||
}
|
||||
|
||||
network = networks[0]
|
||||
|
||||
return false, nil
|
||||
})
|
||||
|
||||
name := tools.RandomString("ACPTTEST", 16)
|
||||
t.Logf("Attempting to create server: %s\n", name)
|
||||
|
||||
pwd := tools.MakeNewPassword("")
|
||||
|
||||
server, err := servers.Create(client, servers.CreateOpts{
|
||||
Name: name,
|
||||
FlavorRef: choices.FlavorID,
|
||||
ImageRef: choices.ImageID,
|
||||
Networks: []servers.Network{
|
||||
servers.Network{UUID: network.ID},
|
||||
},
|
||||
AdminPass: pwd,
|
||||
}).Extract()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create server: %v", err)
|
||||
}
|
||||
|
||||
th.AssertEquals(t, pwd, server.AdminPass)
|
||||
|
||||
return server, err
|
||||
}
|
||||
|
||||
func TestCreateDestroyServer(t *testing.T) {
|
||||
choices, err := ComputeChoicesFromEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
client, err := newClient()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a compute client: %v", err)
|
||||
}
|
||||
|
||||
server, err := createServer(t, client, choices)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create server: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
servers.Delete(client, server.ID)
|
||||
t.Logf("Server deleted.")
|
||||
}()
|
||||
|
||||
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
|
||||
t.Fatalf("Unable to wait for server: %v", err)
|
||||
}
|
||||
|
||||
pager := servers.ListAddresses(client, server.ID)
|
||||
pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
networks, err := servers.ExtractAddresses(page)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for n, a := range networks {
|
||||
t.Logf("%s: %+v\n", n, a)
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
pager = servers.ListAddressesByNetwork(client, server.ID, choices.NetworkName)
|
||||
pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
addresses, err := servers.ExtractNetworkAddresses(page)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, a := range addresses {
|
||||
t.Logf("%+v\n", a)
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateServer(t *testing.T) {
|
||||
client, err := newClient()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a compute client: %v", err)
|
||||
}
|
||||
|
||||
choices, err := ComputeChoicesFromEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
server, err := createServer(t, client, choices)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer servers.Delete(client, server.ID)
|
||||
|
||||
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
alternateName := tools.RandomString("ACPTTEST", 16)
|
||||
for alternateName == server.Name {
|
||||
alternateName = tools.RandomString("ACPTTEST", 16)
|
||||
}
|
||||
|
||||
t.Logf("Attempting to rename the server to %s.", alternateName)
|
||||
|
||||
updated, err := servers.Update(client, server.ID, servers.UpdateOpts{Name: alternateName}).Extract()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to rename server: %v", err)
|
||||
}
|
||||
|
||||
if updated.ID != server.ID {
|
||||
t.Errorf("Updated server ID [%s] didn't match original server ID [%s]!", updated.ID, server.ID)
|
||||
}
|
||||
|
||||
err = tools.WaitFor(func() (bool, error) {
|
||||
latest, err := servers.Get(client, updated.ID).Extract()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return latest.Name == alternateName, nil
|
||||
})
|
||||
}
|
||||
|
||||
func TestActionChangeAdminPassword(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
client, err := newClient()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a compute client: %v", err)
|
||||
}
|
||||
|
||||
choices, err := ComputeChoicesFromEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
server, err := createServer(t, client, choices)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer servers.Delete(client, server.ID)
|
||||
|
||||
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
randomPassword := tools.MakeNewPassword(server.AdminPass)
|
||||
res := servers.ChangeAdminPassword(client, server.ID, randomPassword)
|
||||
if res.Err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = waitForStatus(client, server, "PASSWORD"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestActionReboot(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
client, err := newClient()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a compute client: %v", err)
|
||||
}
|
||||
|
||||
choices, err := ComputeChoicesFromEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
server, err := createServer(t, client, choices)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer servers.Delete(client, server.ID)
|
||||
|
||||
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
res := servers.Reboot(client, server.ID, "aldhjflaskhjf")
|
||||
if res.Err == nil {
|
||||
t.Fatal("Expected the SDK to provide an ArgumentError here")
|
||||
}
|
||||
|
||||
t.Logf("Attempting reboot of server %s", server.ID)
|
||||
res = servers.Reboot(client, server.ID, servers.OSReboot)
|
||||
if res.Err != nil {
|
||||
t.Fatalf("Unable to reboot server: %v", err)
|
||||
}
|
||||
|
||||
if err = waitForStatus(client, server, "REBOOT"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestActionRebuild(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
client, err := newClient()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a compute client: %v", err)
|
||||
}
|
||||
|
||||
choices, err := ComputeChoicesFromEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
server, err := createServer(t, client, choices)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer servers.Delete(client, server.ID)
|
||||
|
||||
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Logf("Attempting to rebuild server %s", server.ID)
|
||||
|
||||
rebuildOpts := servers.RebuildOpts{
|
||||
Name: tools.RandomString("ACPTTEST", 16),
|
||||
AdminPass: tools.MakeNewPassword(server.AdminPass),
|
||||
ImageID: choices.ImageID,
|
||||
}
|
||||
|
||||
rebuilt, err := servers.Rebuild(client, server.ID, rebuildOpts).Extract()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if rebuilt.ID != server.ID {
|
||||
t.Errorf("Expected rebuilt server ID of [%s]; got [%s]", server.ID, rebuilt.ID)
|
||||
}
|
||||
|
||||
if err = waitForStatus(client, rebuilt, "REBUILD"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = waitForStatus(client, rebuilt, "ACTIVE"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func resizeServer(t *testing.T, client *gophercloud.ServiceClient, server *servers.Server, choices *ComputeChoices) {
|
||||
if err := waitForStatus(client, server, "ACTIVE"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Logf("Attempting to resize server [%s]", server.ID)
|
||||
|
||||
opts := &servers.ResizeOpts{
|
||||
FlavorRef: choices.FlavorIDResize,
|
||||
}
|
||||
if res := servers.Resize(client, server.ID, opts); res.Err != nil {
|
||||
t.Fatal(res.Err)
|
||||
}
|
||||
|
||||
if err := waitForStatus(client, server, "VERIFY_RESIZE"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestActionResizeConfirm(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
choices, err := ComputeChoicesFromEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
client, err := newClient()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a compute client: %v", err)
|
||||
}
|
||||
|
||||
server, err := createServer(t, client, choices)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer servers.Delete(client, server.ID)
|
||||
resizeServer(t, client, server, choices)
|
||||
|
||||
t.Logf("Attempting to confirm resize for server %s", server.ID)
|
||||
|
||||
if res := servers.ConfirmResize(client, server.ID); res.Err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestActionResizeRevert(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
choices, err := ComputeChoicesFromEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
client, err := newClient()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a compute client: %v", err)
|
||||
}
|
||||
|
||||
server, err := createServer(t, client, choices)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer servers.Delete(client, server.ID)
|
||||
resizeServer(t, client, server, choices)
|
||||
|
||||
t.Logf("Attempting to revert resize for server %s", server.ID)
|
||||
|
||||
if res := servers.RevertResize(client, server.ID); res.Err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerMetadata(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
choices, err := ComputeChoicesFromEnv()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
client, err := newClient()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a compute client: %v", err)
|
||||
}
|
||||
|
||||
server, err := createServer(t, client, choices)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer servers.Delete(client, server.ID)
|
||||
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
metadata, err := servers.UpdateMetadata(client, server.ID, servers.MetadataOpts{
|
||||
"foo": "bar",
|
||||
"this": "that",
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("UpdateMetadata result: %+v\n", metadata)
|
||||
|
||||
err = servers.DeleteMetadatum(client, server.ID, "foo").ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
metadata, err = servers.CreateMetadatum(client, server.ID, servers.MetadatumOpts{
|
||||
"foo": "baz",
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("CreateMetadatum result: %+v\n", metadata)
|
||||
|
||||
metadata, err = servers.Metadatum(client, server.ID, "foo").Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Metadatum result: %+v\n", metadata)
|
||||
th.AssertEquals(t, "baz", metadata["foo"])
|
||||
|
||||
metadata, err = servers.Metadata(client, server.ID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Metadata result: %+v\n", metadata)
|
||||
|
||||
metadata, err = servers.ResetMetadata(client, server.ID, servers.MetadataOpts{}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("ResetMetadata result: %+v\n", metadata)
|
||||
th.AssertDeepEquals(t, map[string]string{}, metadata)
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
// +build acceptance compute servers
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func getNetworkID(t *testing.T, client *gophercloud.ServiceClient, networkName string) (string, error) {
|
||||
allPages, err := tenantnetworks.List(client).AllPages()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to list networks: %v", err)
|
||||
}
|
||||
|
||||
networkList, err := tenantnetworks.ExtractNetworks(allPages)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to list networks: %v", err)
|
||||
}
|
||||
|
||||
networkID := ""
|
||||
for _, network := range networkList {
|
||||
t.Logf("Network: %v", network)
|
||||
if network.Name == networkName {
|
||||
networkID = network.ID
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("Found network ID for %s: %s\n", networkName, networkID)
|
||||
|
||||
return networkID, nil
|
||||
}
|
||||
|
||||
func createNetworkServer(t *testing.T, client *gophercloud.ServiceClient, choices *ComputeChoices, networkID string) (*servers.Server, error) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping test that requires server creation in short mode.")
|
||||
}
|
||||
|
||||
name := tools.RandomString("ACPTTEST", 16)
|
||||
t.Logf("Attempting to create server: %s\n", name)
|
||||
|
||||
pwd := tools.MakeNewPassword("")
|
||||
|
||||
networks := make([]servers.Network, 1)
|
||||
networks[0] = servers.Network{
|
||||
UUID: networkID,
|
||||
}
|
||||
|
||||
server, err := servers.Create(client, servers.CreateOpts{
|
||||
Name: name,
|
||||
FlavorRef: choices.FlavorID,
|
||||
ImageRef: choices.ImageID,
|
||||
AdminPass: pwd,
|
||||
Networks: networks,
|
||||
}).Extract()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create server: %v", err)
|
||||
}
|
||||
|
||||
th.AssertEquals(t, pwd, server.AdminPass)
|
||||
|
||||
return server, err
|
||||
}
|
||||
|
||||
func TestTenantNetworks(t *testing.T) {
|
||||
networkName := os.Getenv("OS_NETWORK_NAME")
|
||||
if networkName == "" {
|
||||
t.Fatalf("OS_NETWORK_NAME must be set")
|
||||
}
|
||||
|
||||
choices, err := ComputeChoicesFromEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
client, err := newClient()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a compute client: %v", err)
|
||||
}
|
||||
|
||||
networkID, err := getNetworkID(t, client, networkName)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to get network ID: %v", err)
|
||||
}
|
||||
|
||||
server, err := createNetworkServer(t, client, choices, networkID)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create server: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
servers.Delete(client, server.ID)
|
||||
t.Logf("Server deleted.")
|
||||
}()
|
||||
|
||||
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
|
||||
t.Fatalf("Unable to wait for server: %v", err)
|
||||
}
|
||||
|
||||
allPages, err := tenantnetworks.List(client).AllPages()
|
||||
allNetworks, err := tenantnetworks.ExtractNetworks(allPages)
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Retrieved all %d networks: %+v", len(allNetworks), allNetworks)
|
||||
}
|
125
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/volumeattach_test.go
generated
vendored
125
vendor/github.com/rackspace/gophercloud/acceptance/openstack/compute/v2/volumeattach_test.go
generated
vendored
|
@ -1,125 +0,0 @@
|
|||
// +build acceptance compute servers
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||
"github.com/rackspace/gophercloud/openstack"
|
||||
"github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func newBlockClient(t *testing.T) (*gophercloud.ServiceClient, error) {
|
||||
ao, err := openstack.AuthOptionsFromEnv()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
client, err := openstack.AuthenticatedClient(ao)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
return openstack.NewBlockStorageV1(client, gophercloud.EndpointOpts{
|
||||
Region: os.Getenv("OS_REGION_NAME"),
|
||||
})
|
||||
}
|
||||
|
||||
func createVAServer(t *testing.T, computeClient *gophercloud.ServiceClient, choices *ComputeChoices) (*servers.Server, error) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping test that requires server creation in short mode.")
|
||||
}
|
||||
|
||||
name := tools.RandomString("ACPTTEST", 16)
|
||||
t.Logf("Attempting to create server: %s\n", name)
|
||||
|
||||
pwd := tools.MakeNewPassword("")
|
||||
|
||||
server, err := servers.Create(computeClient, servers.CreateOpts{
|
||||
Name: name,
|
||||
FlavorRef: choices.FlavorID,
|
||||
ImageRef: choices.ImageID,
|
||||
AdminPass: pwd,
|
||||
}).Extract()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create server: %v", err)
|
||||
}
|
||||
|
||||
th.AssertEquals(t, pwd, server.AdminPass)
|
||||
|
||||
return server, err
|
||||
}
|
||||
|
||||
func createVAVolume(t *testing.T, blockClient *gophercloud.ServiceClient) (*volumes.Volume, error) {
|
||||
volume, err := volumes.Create(blockClient, &volumes.CreateOpts{
|
||||
Size: 1,
|
||||
Name: "gophercloud-test-volume",
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
defer func() {
|
||||
err = volumes.WaitForStatus(blockClient, volume.ID, "available", 60)
|
||||
th.AssertNoErr(t, err)
|
||||
}()
|
||||
|
||||
return volume, err
|
||||
}
|
||||
|
||||
func createVolumeAttachment(t *testing.T, computeClient *gophercloud.ServiceClient, blockClient *gophercloud.ServiceClient, serverId string, volumeId string) {
|
||||
va, err := volumeattach.Create(computeClient, serverId, &volumeattach.CreateOpts{
|
||||
VolumeID: volumeId,
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
defer func() {
|
||||
err = volumes.WaitForStatus(blockClient, volumeId, "in-use", 60)
|
||||
th.AssertNoErr(t, err)
|
||||
err = volumeattach.Delete(computeClient, serverId, va.ID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
err = volumes.WaitForStatus(blockClient, volumeId, "available", 60)
|
||||
th.AssertNoErr(t, err)
|
||||
}()
|
||||
}
|
||||
|
||||
func TestAttachVolume(t *testing.T) {
|
||||
choices, err := ComputeChoicesFromEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
computeClient, err := newClient()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a compute client: %v", err)
|
||||
}
|
||||
|
||||
blockClient, err := newBlockClient(t)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create a blockstorage client: %v", err)
|
||||
}
|
||||
|
||||
server, err := createVAServer(t, computeClient, choices)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create server: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
servers.Delete(computeClient, server.ID)
|
||||
t.Logf("Server deleted.")
|
||||
}()
|
||||
|
||||
if err = waitForStatus(computeClient, server, "ACTIVE"); err != nil {
|
||||
t.Fatalf("Unable to wait for server: %v", err)
|
||||
}
|
||||
|
||||
volume, err := createVAVolume(t, blockClient)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create volume: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
err = volumes.Delete(blockClient, volume.ID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Volume deleted.")
|
||||
}()
|
||||
|
||||
createVolumeAttachment(t, computeClient, blockClient, server.ID, volume.ID)
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
// +build acceptance identity
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
extensions2 "github.com/rackspace/gophercloud/openstack/identity/v2/extensions"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestEnumerateExtensions(t *testing.T) {
|
||||
service := authenticatedClient(t)
|
||||
|
||||
t.Logf("Extensions available on this identity endpoint:")
|
||||
count := 0
|
||||
err := extensions2.List(service).EachPage(func(page pagination.Page) (bool, error) {
|
||||
t.Logf("--- Page %02d ---", count)
|
||||
|
||||
extensions, err := extensions2.ExtractExtensions(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for i, ext := range extensions {
|
||||
t.Logf("[%02d] name=[%s] namespace=[%s]", i, ext.Name, ext.Namespace)
|
||||
t.Logf(" alias=[%s] updated=[%s]", ext.Alias, ext.Updated)
|
||||
t.Logf(" description=[%s]", ext.Description)
|
||||
}
|
||||
|
||||
count++
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func TestGetExtension(t *testing.T) {
|
||||
service := authenticatedClient(t)
|
||||
|
||||
ext, err := extensions2.Get(service, "OS-KSCRUD").Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
th.CheckEquals(t, "OpenStack Keystone User CRUD", ext.Name)
|
||||
th.CheckEquals(t, "http://docs.openstack.org/identity/api/ext/OS-KSCRUD/v1.0", ext.Namespace)
|
||||
th.CheckEquals(t, "OS-KSCRUD", ext.Alias)
|
||||
th.CheckEquals(t, "OpenStack extensions to Keystone v2.0 API enabling User Operations.", ext.Description)
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
// +build acceptance identity
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func v2AuthOptions(t *testing.T) gophercloud.AuthOptions {
|
||||
// Obtain credentials from the environment.
|
||||
ao, err := openstack.AuthOptionsFromEnv()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
// Trim out unused fields. Prefer authentication by API key to password.
|
||||
ao.UserID, ao.DomainID, ao.DomainName = "", "", ""
|
||||
if ao.APIKey != "" {
|
||||
ao.Password = ""
|
||||
}
|
||||
|
||||
return ao
|
||||
}
|
||||
|
||||
func createClient(t *testing.T, auth bool) *gophercloud.ServiceClient {
|
||||
ao := v2AuthOptions(t)
|
||||
|
||||
provider, err := openstack.NewClient(ao.IdentityEndpoint)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
if auth {
|
||||
err = openstack.AuthenticateV2(provider, ao)
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
return openstack.NewIdentityV2(provider)
|
||||
}
|
||||
|
||||
func unauthenticatedClient(t *testing.T) *gophercloud.ServiceClient {
|
||||
return createClient(t, false)
|
||||
}
|
||||
|
||||
func authenticatedClient(t *testing.T) *gophercloud.ServiceClient {
|
||||
return createClient(t, true)
|
||||
}
|
58
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v2/role_test.go
generated
vendored
58
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v2/role_test.go
generated
vendored
|
@ -1,58 +0,0 @@
|
|||
// +build acceptance identity roles
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestRoles(t *testing.T) {
|
||||
client := authenticatedClient(t)
|
||||
|
||||
tenantID := findTenant(t, client)
|
||||
userID := createUser(t, client, tenantID)
|
||||
roleID := listRoles(t, client)
|
||||
|
||||
addUserRole(t, client, tenantID, userID, roleID)
|
||||
|
||||
deleteUserRole(t, client, tenantID, userID, roleID)
|
||||
|
||||
deleteUser(t, client, userID)
|
||||
}
|
||||
|
||||
func listRoles(t *testing.T, client *gophercloud.ServiceClient) string {
|
||||
var roleID string
|
||||
|
||||
err := roles.List(client).EachPage(func(page pagination.Page) (bool, error) {
|
||||
roleList, err := roles.ExtractRoles(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, role := range roleList {
|
||||
t.Logf("Listing role: ID [%s] Name [%s]", role.ID, role.Name)
|
||||
roleID = role.ID
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
return roleID
|
||||
}
|
||||
|
||||
func addUserRole(t *testing.T, client *gophercloud.ServiceClient, tenantID, userID, roleID string) {
|
||||
err := roles.AddUserRole(client, tenantID, userID, roleID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Added role %s to user %s", roleID, userID)
|
||||
}
|
||||
|
||||
func deleteUserRole(t *testing.T, client *gophercloud.ServiceClient, tenantID, userID, roleID string) {
|
||||
err := roles.DeleteUserRole(client, tenantID, userID, roleID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Removed role %s from user %s", roleID, userID)
|
||||
}
|
32
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v2/tenant_test.go
generated
vendored
32
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v2/tenant_test.go
generated
vendored
|
@ -1,32 +0,0 @@
|
|||
// +build acceptance identity
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
tenants2 "github.com/rackspace/gophercloud/openstack/identity/v2/tenants"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestEnumerateTenants(t *testing.T) {
|
||||
service := authenticatedClient(t)
|
||||
|
||||
t.Logf("Tenants to which your current token grants access:")
|
||||
count := 0
|
||||
err := tenants2.List(service, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||
t.Logf("--- Page %02d ---", count)
|
||||
|
||||
tenants, err := tenants2.ExtractTenants(page)
|
||||
th.AssertNoErr(t, err)
|
||||
for i, tenant := range tenants {
|
||||
t.Logf("[%02d] name=[%s] id=[%s] description=[%s] enabled=[%v]",
|
||||
i, tenant.Name, tenant.ID, tenant.Description, tenant.Enabled)
|
||||
}
|
||||
|
||||
count++
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
38
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v2/token_test.go
generated
vendored
38
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v2/token_test.go
generated
vendored
|
@ -1,38 +0,0 @@
|
|||
// +build acceptance identity
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
tokens2 "github.com/rackspace/gophercloud/openstack/identity/v2/tokens"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestAuthenticate(t *testing.T) {
|
||||
ao := v2AuthOptions(t)
|
||||
service := unauthenticatedClient(t)
|
||||
|
||||
// Authenticated!
|
||||
result := tokens2.Create(service, tokens2.WrapOptions(ao))
|
||||
|
||||
// Extract and print the token.
|
||||
token, err := result.ExtractToken()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Acquired token: [%s]", token.ID)
|
||||
t.Logf("The token will expire at: [%s]", token.ExpiresAt.String())
|
||||
t.Logf("The token is valid for tenant: [%#v]", token.Tenant)
|
||||
|
||||
// Extract and print the service catalog.
|
||||
catalog, err := result.ExtractServiceCatalog()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Acquired service catalog listing [%d] services", len(catalog.Entries))
|
||||
for i, entry := range catalog.Entries {
|
||||
t.Logf("[%02d]: name=[%s], type=[%s]", i, entry.Name, entry.Type)
|
||||
for _, endpoint := range entry.Endpoints {
|
||||
t.Logf(" - region=[%s] publicURL=[%s]", endpoint.Region, endpoint.PublicURL)
|
||||
}
|
||||
}
|
||||
}
|
127
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v2/user_test.go
generated
vendored
127
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v2/user_test.go
generated
vendored
|
@ -1,127 +0,0 @@
|
|||
// +build acceptance identity
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||
"github.com/rackspace/gophercloud/openstack/identity/v2/tenants"
|
||||
"github.com/rackspace/gophercloud/openstack/identity/v2/users"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestUsers(t *testing.T) {
|
||||
client := authenticatedClient(t)
|
||||
|
||||
tenantID := findTenant(t, client)
|
||||
|
||||
userID := createUser(t, client, tenantID)
|
||||
|
||||
listUsers(t, client)
|
||||
|
||||
getUser(t, client, userID)
|
||||
|
||||
updateUser(t, client, userID)
|
||||
|
||||
listUserRoles(t, client, tenantID, userID)
|
||||
|
||||
deleteUser(t, client, userID)
|
||||
}
|
||||
|
||||
func findTenant(t *testing.T, client *gophercloud.ServiceClient) string {
|
||||
var tenantID string
|
||||
err := tenants.List(client, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||
tenantList, err := tenants.ExtractTenants(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, t := range tenantList {
|
||||
tenantID = t.ID
|
||||
break
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
return tenantID
|
||||
}
|
||||
|
||||
func createUser(t *testing.T, client *gophercloud.ServiceClient, tenantID string) string {
|
||||
t.Log("Creating user")
|
||||
|
||||
opts := users.CreateOpts{
|
||||
Name: tools.RandomString("user_", 5),
|
||||
Enabled: users.Disabled,
|
||||
TenantID: tenantID,
|
||||
Email: "new_user@foo.com",
|
||||
}
|
||||
|
||||
user, err := users.Create(client, opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Created user %s on tenant %s", user.ID, tenantID)
|
||||
|
||||
return user.ID
|
||||
}
|
||||
|
||||
func listUsers(t *testing.T, client *gophercloud.ServiceClient) {
|
||||
err := users.List(client).EachPage(func(page pagination.Page) (bool, error) {
|
||||
userList, err := users.ExtractUsers(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, user := range userList {
|
||||
t.Logf("Listing user: ID [%s] Name [%s] Email [%s] Enabled? [%s]",
|
||||
user.ID, user.Name, user.Email, strconv.FormatBool(user.Enabled))
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func getUser(t *testing.T, client *gophercloud.ServiceClient, userID string) {
|
||||
_, err := users.Get(client, userID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Getting user %s", userID)
|
||||
}
|
||||
|
||||
func updateUser(t *testing.T, client *gophercloud.ServiceClient, userID string) {
|
||||
opts := users.UpdateOpts{Name: tools.RandomString("new_name", 5), Email: "new@foo.com"}
|
||||
user, err := users.Update(client, userID, opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Updated user %s: Name [%s] Email [%s]", userID, user.Name, user.Email)
|
||||
}
|
||||
|
||||
func listUserRoles(t *testing.T, client *gophercloud.ServiceClient, tenantID, userID string) {
|
||||
count := 0
|
||||
err := users.ListRoles(client, tenantID, userID).EachPage(func(page pagination.Page) (bool, error) {
|
||||
count++
|
||||
|
||||
roleList, err := users.ExtractRoles(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Listing roles for user %s", userID)
|
||||
|
||||
for _, r := range roleList {
|
||||
t.Logf("- %s (%s)", r.Name, r.ID)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
if count == 0 {
|
||||
t.Logf("No roles for user %s", userID)
|
||||
}
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func deleteUser(t *testing.T, client *gophercloud.ServiceClient, userID string) {
|
||||
res := users.Delete(client, userID)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
t.Logf("Deleted user %s", userID)
|
||||
}
|
111
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v3/endpoint_test.go
generated
vendored
111
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v3/endpoint_test.go
generated
vendored
|
@ -1,111 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v3
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
endpoints3 "github.com/rackspace/gophercloud/openstack/identity/v3/endpoints"
|
||||
services3 "github.com/rackspace/gophercloud/openstack/identity/v3/services"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
func TestListEndpoints(t *testing.T) {
|
||||
// Create a service client.
|
||||
serviceClient := createAuthenticatedClient(t)
|
||||
if serviceClient == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Use the service to list all available endpoints.
|
||||
pager := endpoints3.List(serviceClient, endpoints3.ListOpts{})
|
||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
t.Logf("--- Page ---")
|
||||
|
||||
endpoints, err := endpoints3.ExtractEndpoints(page)
|
||||
if err != nil {
|
||||
t.Fatalf("Error extracting endpoings: %v", err)
|
||||
}
|
||||
|
||||
for _, endpoint := range endpoints {
|
||||
t.Logf("Endpoint: %8s %10s %9s %s",
|
||||
endpoint.ID,
|
||||
endpoint.Availability,
|
||||
endpoint.Name,
|
||||
endpoint.URL)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error while iterating endpoint pages: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNavigateCatalog(t *testing.T) {
|
||||
// Create a service client.
|
||||
client := createAuthenticatedClient(t)
|
||||
if client == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var compute *services3.Service
|
||||
var endpoint *endpoints3.Endpoint
|
||||
|
||||
// Discover the service we're interested in.
|
||||
servicePager := services3.List(client, services3.ListOpts{ServiceType: "compute"})
|
||||
err := servicePager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
part, err := services3.ExtractServices(page)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if compute != nil {
|
||||
t.Fatalf("Expected one service, got more than one page")
|
||||
return false, nil
|
||||
}
|
||||
if len(part) != 1 {
|
||||
t.Fatalf("Expected one service, got %d", len(part))
|
||||
return false, nil
|
||||
}
|
||||
|
||||
compute = &part[0]
|
||||
return true, nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error iterating pages: %v", err)
|
||||
}
|
||||
|
||||
if compute == nil {
|
||||
t.Fatalf("No compute service found.")
|
||||
}
|
||||
|
||||
// Enumerate the endpoints available for this service.
|
||||
computePager := endpoints3.List(client, endpoints3.ListOpts{
|
||||
Availability: gophercloud.AvailabilityPublic,
|
||||
ServiceID: compute.ID,
|
||||
})
|
||||
err = computePager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
part, err := endpoints3.ExtractEndpoints(page)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if endpoint != nil {
|
||||
t.Fatalf("Expected one endpoint, got more than one page")
|
||||
return false, nil
|
||||
}
|
||||
if len(part) != 1 {
|
||||
t.Fatalf("Expected one endpoint, got %d", len(part))
|
||||
return false, nil
|
||||
}
|
||||
|
||||
endpoint = &part[0]
|
||||
return true, nil
|
||||
})
|
||||
|
||||
if endpoint == nil {
|
||||
t.Fatalf("No endpoint found.")
|
||||
}
|
||||
|
||||
t.Logf("Success. The compute endpoint is at %s.", endpoint.URL)
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v3
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func createAuthenticatedClient(t *testing.T) *gophercloud.ServiceClient {
|
||||
// Obtain credentials from the environment.
|
||||
ao, err := openstack.AuthOptionsFromEnv()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
// Trim out unused fields.
|
||||
ao.Username, ao.TenantID, ao.TenantName = "", "", ""
|
||||
|
||||
if ao.UserID == "" {
|
||||
t.Logf("Skipping identity v3 tests because no OS_USERID is present.")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create a client and manually authenticate against v3.
|
||||
providerClient, err := openstack.NewClient(ao.IdentityEndpoint)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to instantiate client: %v", err)
|
||||
}
|
||||
|
||||
err = openstack.AuthenticateV3(providerClient, ao)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to authenticate against identity v3: %v", err)
|
||||
}
|
||||
|
||||
// Create a service client.
|
||||
return openstack.NewIdentityV3(providerClient)
|
||||
}
|
36
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v3/service_test.go
generated
vendored
36
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v3/service_test.go
generated
vendored
|
@ -1,36 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v3
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
services3 "github.com/rackspace/gophercloud/openstack/identity/v3/services"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
func TestListServices(t *testing.T) {
|
||||
// Create a service client.
|
||||
serviceClient := createAuthenticatedClient(t)
|
||||
if serviceClient == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Use the client to list all available services.
|
||||
pager := services3.List(serviceClient, services3.ListOpts{})
|
||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
parts, err := services3.ExtractServices(page)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
t.Logf("--- Page ---")
|
||||
for _, service := range parts {
|
||||
t.Logf("Service: %32s %15s %10s %s", service.ID, service.Type, service.Name, *service.Description)
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error traversing pages: %v", err)
|
||||
}
|
||||
}
|
42
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v3/token_test.go
generated
vendored
42
vendor/github.com/rackspace/gophercloud/acceptance/openstack/identity/v3/token_test.go
generated
vendored
|
@ -1,42 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v3
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack"
|
||||
tokens3 "github.com/rackspace/gophercloud/openstack/identity/v3/tokens"
|
||||
)
|
||||
|
||||
func TestGetToken(t *testing.T) {
|
||||
// Obtain credentials from the environment.
|
||||
ao, err := openstack.AuthOptionsFromEnv()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to acquire credentials: %v", err)
|
||||
}
|
||||
|
||||
// Trim out unused fields. Skip if we don't have a UserID.
|
||||
ao.Username, ao.TenantID, ao.TenantName = "", "", ""
|
||||
if ao.UserID == "" {
|
||||
t.Logf("Skipping identity v3 tests because no OS_USERID is present.")
|
||||
return
|
||||
}
|
||||
|
||||
// Create an unauthenticated client.
|
||||
provider, err := openstack.NewClient(ao.IdentityEndpoint)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to instantiate client: %v", err)
|
||||
}
|
||||
|
||||
// Create a service client.
|
||||
service := openstack.NewIdentityV3(provider)
|
||||
|
||||
// Use the service to create a token.
|
||||
token, err := tokens3.Create(service, ao, nil).Extract()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to get token: %v", err)
|
||||
}
|
||||
|
||||
t.Logf("Acquired token: %s", token.ID)
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
// +build acceptance networking
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/apiversions"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestListAPIVersions(t *testing.T) {
|
||||
Setup(t)
|
||||
defer Teardown()
|
||||
|
||||
pager := apiversions.ListVersions(Client)
|
||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
t.Logf("--- Page ---")
|
||||
|
||||
versions, err := apiversions.ExtractAPIVersions(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, v := range versions {
|
||||
t.Logf("API Version: ID [%s] Status [%s]", v.ID, v.Status)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.CheckNoErr(t, err)
|
||||
}
|
||||
|
||||
func TestListAPIResources(t *testing.T) {
|
||||
Setup(t)
|
||||
defer Teardown()
|
||||
|
||||
pager := apiversions.ListVersionResources(Client, "v2.0")
|
||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
t.Logf("--- Page ---")
|
||||
|
||||
vrs, err := apiversions.ExtractVersionResources(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, vr := range vrs {
|
||||
t.Logf("Network: Name [%s] Collection [%s]", vr.Name, vr.Collection)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.CheckNoErr(t, err)
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
// +build acceptance networking
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestListExts(t *testing.T) {
|
||||
Setup(t)
|
||||
defer Teardown()
|
||||
|
||||
pager := extensions.List(Client)
|
||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
t.Logf("--- Page ---")
|
||||
|
||||
exts, err := extensions.ExtractExtensions(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, ext := range exts {
|
||||
t.Logf("Extension: Name [%s] Description [%s]", ext.Name, ext.Description)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.CheckNoErr(t, err)
|
||||
}
|
||||
|
||||
func TestGetExt(t *testing.T) {
|
||||
Setup(t)
|
||||
defer Teardown()
|
||||
|
||||
ext, err := extensions.Get(Client, "service-type").Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
th.AssertEquals(t, ext.Updated, "2013-01-20T00:00:00-00:00")
|
||||
th.AssertEquals(t, ext.Name, "Neutron Service Type Management")
|
||||
th.AssertEquals(t, ext.Namespace, "http://docs.openstack.org/ext/neutron/service-type/api/v1.0")
|
||||
th.AssertEquals(t, ext.Alias, "service-type")
|
||||
th.AssertEquals(t, ext.Description, "API for retrieving service providers for Neutron advanced services")
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
// +build acceptance networking fwaas
|
||||
|
||||
package fwaas
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func firewallSetup(t *testing.T) string {
|
||||
base.Setup(t)
|
||||
return createPolicy(t, &policies.CreateOpts{})
|
||||
}
|
||||
|
||||
func firewallTeardown(t *testing.T, policyID string) {
|
||||
defer base.Teardown()
|
||||
deletePolicy(t, policyID)
|
||||
}
|
||||
|
||||
func TestFirewall(t *testing.T) {
|
||||
policyID := firewallSetup(t)
|
||||
defer firewallTeardown(t, policyID)
|
||||
|
||||
firewallID := createFirewall(t, &firewalls.CreateOpts{
|
||||
Name: "gophercloud test",
|
||||
Description: "acceptance test",
|
||||
PolicyID: policyID,
|
||||
})
|
||||
|
||||
waitForFirewallToBeActive(t, firewallID)
|
||||
|
||||
listFirewalls(t)
|
||||
|
||||
updateFirewall(t, firewallID, &firewalls.UpdateOpts{
|
||||
Description: "acceptance test updated",
|
||||
})
|
||||
|
||||
waitForFirewallToBeActive(t, firewallID)
|
||||
|
||||
deleteFirewall(t, firewallID)
|
||||
|
||||
waitForFirewallToBeDeleted(t, firewallID)
|
||||
}
|
||||
|
||||
func createFirewall(t *testing.T, opts *firewalls.CreateOpts) string {
|
||||
f, err := firewalls.Create(base.Client, *opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Created firewall: %#v", opts)
|
||||
return f.ID
|
||||
}
|
||||
|
||||
func listFirewalls(t *testing.T) {
|
||||
err := firewalls.List(base.Client, firewalls.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
|
||||
firewallList, err := firewalls.ExtractFirewalls(page)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to extract firewalls: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, r := range firewallList {
|
||||
t.Logf("Listing firewalls: ID [%s]", r.ID)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func updateFirewall(t *testing.T, firewallID string, opts *firewalls.UpdateOpts) {
|
||||
f, err := firewalls.Update(base.Client, firewallID, *opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Updated firewall ID [%s]", f.ID)
|
||||
}
|
||||
|
||||
func getFirewall(t *testing.T, firewallID string) *firewalls.Firewall {
|
||||
f, err := firewalls.Get(base.Client, firewallID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Getting firewall ID [%s]", f.ID)
|
||||
return f
|
||||
}
|
||||
|
||||
func deleteFirewall(t *testing.T, firewallID string) {
|
||||
res := firewalls.Delete(base.Client, firewallID)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
t.Logf("Deleted firewall %s", firewallID)
|
||||
}
|
||||
|
||||
func waitForFirewallToBeActive(t *testing.T, firewallID string) {
|
||||
for i := 0; i < 10; i++ {
|
||||
fw := getFirewall(t, firewallID)
|
||||
if fw.Status == "ACTIVE" {
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func waitForFirewallToBeDeleted(t *testing.T, firewallID string) {
|
||||
for i := 0; i < 10; i++ {
|
||||
err := firewalls.Get(base.Client, firewallID).Err
|
||||
if err != nil {
|
||||
httpStatus := err.(*gophercloud.UnexpectedResponseCodeError)
|
||||
if httpStatus.Actual == 404 {
|
||||
return
|
||||
}
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
// +build acceptance networking fwaas
|
||||
|
||||
package fwaas
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func firewallPolicySetup(t *testing.T) string {
|
||||
base.Setup(t)
|
||||
return createRule(t, &rules.CreateOpts{
|
||||
Protocol: "tcp",
|
||||
Action: "allow",
|
||||
})
|
||||
}
|
||||
|
||||
func firewallPolicyTeardown(t *testing.T, ruleID string) {
|
||||
defer base.Teardown()
|
||||
deleteRule(t, ruleID)
|
||||
}
|
||||
|
||||
func TestFirewallPolicy(t *testing.T) {
|
||||
ruleID := firewallPolicySetup(t)
|
||||
defer firewallPolicyTeardown(t, ruleID)
|
||||
|
||||
policyID := createPolicy(t, &policies.CreateOpts{
|
||||
Name: "gophercloud test",
|
||||
Description: "acceptance test",
|
||||
Rules: []string{
|
||||
ruleID,
|
||||
},
|
||||
})
|
||||
|
||||
listPolicies(t)
|
||||
|
||||
updatePolicy(t, policyID, &policies.UpdateOpts{
|
||||
Description: "acceptance test updated",
|
||||
})
|
||||
|
||||
getPolicy(t, policyID)
|
||||
|
||||
removeRuleFromPolicy(t, policyID, ruleID)
|
||||
|
||||
addRuleToPolicy(t, policyID, ruleID)
|
||||
|
||||
deletePolicy(t, policyID)
|
||||
}
|
||||
|
||||
func createPolicy(t *testing.T, opts *policies.CreateOpts) string {
|
||||
p, err := policies.Create(base.Client, *opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Created policy: %#v", opts)
|
||||
return p.ID
|
||||
}
|
||||
|
||||
func listPolicies(t *testing.T) {
|
||||
err := policies.List(base.Client, policies.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
|
||||
policyList, err := policies.ExtractPolicies(page)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to extract policies: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, p := range policyList {
|
||||
t.Logf("Listing policies: ID [%s]", p.ID)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func updatePolicy(t *testing.T, policyID string, opts *policies.UpdateOpts) {
|
||||
p, err := policies.Update(base.Client, policyID, *opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Updated policy ID [%s]", p.ID)
|
||||
}
|
||||
|
||||
func removeRuleFromPolicy(t *testing.T, policyID string, ruleID string) {
|
||||
err := policies.RemoveRule(base.Client, policyID, ruleID)
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Removed rule [%s] from policy ID [%s]", ruleID, policyID)
|
||||
}
|
||||
|
||||
func addRuleToPolicy(t *testing.T, policyID string, ruleID string) {
|
||||
err := policies.InsertRule(base.Client, policyID, ruleID, "", "")
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Inserted rule [%s] into policy ID [%s]", ruleID, policyID)
|
||||
}
|
||||
|
||||
func getPolicy(t *testing.T, policyID string) {
|
||||
p, err := policies.Get(base.Client, policyID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Getting policy ID [%s]", p.ID)
|
||||
}
|
||||
|
||||
func deletePolicy(t *testing.T, policyID string) {
|
||||
res := policies.Delete(base.Client, policyID)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
t.Logf("Deleted policy %s", policyID)
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
// +build acceptance networking fwaas
|
||||
|
||||
package fwaas
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestFirewallRules(t *testing.T) {
|
||||
base.Setup(t)
|
||||
defer base.Teardown()
|
||||
|
||||
ruleID := createRule(t, &rules.CreateOpts{
|
||||
Name: "gophercloud_test",
|
||||
Description: "acceptance test",
|
||||
Protocol: "tcp",
|
||||
Action: "allow",
|
||||
DestinationIPAddress: "192.168.0.0/24",
|
||||
DestinationPort: "22",
|
||||
})
|
||||
|
||||
listRules(t)
|
||||
|
||||
destinationIPAddress := "192.168.1.0/24"
|
||||
destinationPort := ""
|
||||
sourcePort := "1234"
|
||||
|
||||
updateRule(t, ruleID, &rules.UpdateOpts{
|
||||
DestinationIPAddress: &destinationIPAddress,
|
||||
DestinationPort: &destinationPort,
|
||||
SourcePort: &sourcePort,
|
||||
})
|
||||
|
||||
getRule(t, ruleID)
|
||||
|
||||
deleteRule(t, ruleID)
|
||||
}
|
||||
|
||||
func createRule(t *testing.T, opts *rules.CreateOpts) string {
|
||||
r, err := rules.Create(base.Client, *opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Created rule: %#v", opts)
|
||||
return r.ID
|
||||
}
|
||||
|
||||
func listRules(t *testing.T) {
|
||||
err := rules.List(base.Client, rules.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
|
||||
ruleList, err := rules.ExtractRules(page)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to extract rules: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, r := range ruleList {
|
||||
t.Logf("Listing rules: ID [%s]", r.ID)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func updateRule(t *testing.T, ruleID string, opts *rules.UpdateOpts) {
|
||||
r, err := rules.Update(base.Client, ruleID, *opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Updated rule ID [%s]", r.ID)
|
||||
}
|
||||
|
||||
func getRule(t *testing.T, ruleID string) {
|
||||
r, err := rules.Get(base.Client, ruleID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Getting rule ID [%s]", r.ID)
|
||||
}
|
||||
|
||||
func deleteRule(t *testing.T, ruleID string) {
|
||||
res := rules.Delete(base.Client, ruleID)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
t.Logf("Deleted rule %s", ruleID)
|
||||
}
|
|
@ -1,300 +0,0 @@
|
|||
// +build acceptance networking layer3ext
|
||||
|
||||
package extensions
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/external"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/ports"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/subnets"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
const (
|
||||
cidr1 = "10.0.0.1/24"
|
||||
cidr2 = "20.0.0.1/24"
|
||||
)
|
||||
|
||||
func TestAll(t *testing.T) {
|
||||
base.Setup(t)
|
||||
defer base.Teardown()
|
||||
|
||||
testRouter(t)
|
||||
testFloatingIP(t)
|
||||
}
|
||||
|
||||
func testRouter(t *testing.T) {
|
||||
// Setup: Create network
|
||||
networkID := createNetwork(t)
|
||||
|
||||
// Create router
|
||||
routerID := createRouter(t, networkID)
|
||||
|
||||
// Lists routers
|
||||
listRouters(t)
|
||||
|
||||
// Update router
|
||||
updateRouter(t, routerID)
|
||||
|
||||
// Get router
|
||||
getRouter(t, routerID)
|
||||
|
||||
// Create new subnet. Note: this subnet will be deleted when networkID is deleted
|
||||
subnetID := createSubnet(t, networkID, cidr2)
|
||||
|
||||
// Add interface
|
||||
addInterface(t, routerID, subnetID)
|
||||
|
||||
// Remove interface
|
||||
removeInterface(t, routerID, subnetID)
|
||||
|
||||
// Delete router
|
||||
deleteRouter(t, routerID)
|
||||
|
||||
// Cleanup
|
||||
deleteNetwork(t, networkID)
|
||||
}
|
||||
|
||||
func testFloatingIP(t *testing.T) {
|
||||
// Setup external network
|
||||
extNetworkID := createNetwork(t)
|
||||
|
||||
// Setup internal network, subnet and port
|
||||
intNetworkID, subnetID, portID := createInternalTopology(t)
|
||||
|
||||
// Now the important part: we need to allow the external network to talk to
|
||||
// the internal subnet. For this we need a router that has an interface to
|
||||
// the internal subnet.
|
||||
routerID := bridgeIntSubnetWithExtNetwork(t, extNetworkID, subnetID)
|
||||
|
||||
// Create floating IP
|
||||
ipID := createFloatingIP(t, extNetworkID, portID)
|
||||
|
||||
// Get floating IP
|
||||
getFloatingIP(t, ipID)
|
||||
|
||||
// Update floating IP
|
||||
updateFloatingIP(t, ipID, portID)
|
||||
|
||||
// Delete floating IP
|
||||
deleteFloatingIP(t, ipID)
|
||||
|
||||
// Remove the internal subnet interface
|
||||
removeInterface(t, routerID, subnetID)
|
||||
|
||||
// Delete router and external network
|
||||
deleteRouter(t, routerID)
|
||||
deleteNetwork(t, extNetworkID)
|
||||
|
||||
// Delete internal port and network
|
||||
deletePort(t, portID)
|
||||
deleteNetwork(t, intNetworkID)
|
||||
}
|
||||
|
||||
func createNetwork(t *testing.T) string {
|
||||
t.Logf("Creating a network")
|
||||
|
||||
asu := true
|
||||
opts := external.CreateOpts{
|
||||
Parent: networks.CreateOpts{Name: "sample_network", AdminStateUp: &asu},
|
||||
External: true,
|
||||
}
|
||||
n, err := networks.Create(base.Client, opts).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
if n.ID == "" {
|
||||
t.Fatalf("No ID returned when creating a network")
|
||||
}
|
||||
|
||||
createSubnet(t, n.ID, cidr1)
|
||||
|
||||
t.Logf("Network created: ID [%s]", n.ID)
|
||||
|
||||
return n.ID
|
||||
}
|
||||
|
||||
func deleteNetwork(t *testing.T, networkID string) {
|
||||
t.Logf("Deleting network %s", networkID)
|
||||
networks.Delete(base.Client, networkID)
|
||||
}
|
||||
|
||||
func deletePort(t *testing.T, portID string) {
|
||||
t.Logf("Deleting port %s", portID)
|
||||
ports.Delete(base.Client, portID)
|
||||
}
|
||||
|
||||
func createInternalTopology(t *testing.T) (string, string, string) {
|
||||
t.Logf("Creating an internal network (for port)")
|
||||
opts := networks.CreateOpts{Name: "internal_network"}
|
||||
n, err := networks.Create(base.Client, opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
// A subnet is also needed
|
||||
subnetID := createSubnet(t, n.ID, cidr2)
|
||||
|
||||
t.Logf("Creating an internal port on network %s", n.ID)
|
||||
p, err := ports.Create(base.Client, ports.CreateOpts{
|
||||
NetworkID: n.ID,
|
||||
Name: "fixed_internal_port",
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
return n.ID, subnetID, p.ID
|
||||
}
|
||||
|
||||
func bridgeIntSubnetWithExtNetwork(t *testing.T, networkID, subnetID string) string {
|
||||
// Create router with external gateway info
|
||||
routerID := createRouter(t, networkID)
|
||||
|
||||
// Add interface for internal subnet
|
||||
addInterface(t, routerID, subnetID)
|
||||
|
||||
return routerID
|
||||
}
|
||||
|
||||
func createSubnet(t *testing.T, networkID, cidr string) string {
|
||||
t.Logf("Creating a subnet for network %s", networkID)
|
||||
|
||||
iFalse := false
|
||||
s, err := subnets.Create(base.Client, subnets.CreateOpts{
|
||||
NetworkID: networkID,
|
||||
CIDR: cidr,
|
||||
IPVersion: subnets.IPv4,
|
||||
Name: "my_subnet",
|
||||
EnableDHCP: &iFalse,
|
||||
}).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Subnet created: ID [%s]", s.ID)
|
||||
|
||||
return s.ID
|
||||
}
|
||||
|
||||
func createRouter(t *testing.T, networkID string) string {
|
||||
t.Logf("Creating a router for network %s", networkID)
|
||||
|
||||
asu := false
|
||||
gwi := routers.GatewayInfo{NetworkID: networkID}
|
||||
r, err := routers.Create(base.Client, routers.CreateOpts{
|
||||
Name: "foo_router",
|
||||
AdminStateUp: &asu,
|
||||
GatewayInfo: &gwi,
|
||||
}).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
if r.ID == "" {
|
||||
t.Fatalf("No ID returned when creating a router")
|
||||
}
|
||||
|
||||
t.Logf("Router created: ID [%s]", r.ID)
|
||||
|
||||
return r.ID
|
||||
}
|
||||
|
||||
func listRouters(t *testing.T) {
|
||||
pager := routers.List(base.Client, routers.ListOpts{})
|
||||
|
||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
routerList, err := routers.ExtractRouters(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, r := range routerList {
|
||||
t.Logf("Listing router: ID [%s] Name [%s] Status [%s] GatewayInfo [%#v]",
|
||||
r.ID, r.Name, r.Status, r.GatewayInfo)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func updateRouter(t *testing.T, routerID string) {
|
||||
_, err := routers.Update(base.Client, routerID, routers.UpdateOpts{
|
||||
Name: "another_name",
|
||||
}).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func getRouter(t *testing.T, routerID string) {
|
||||
r, err := routers.Get(base.Client, routerID).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Getting router: ID [%s] Name [%s] Status [%s]", r.ID, r.Name, r.Status)
|
||||
}
|
||||
|
||||
func addInterface(t *testing.T, routerID, subnetID string) {
|
||||
ir, err := routers.AddInterface(base.Client, routerID, routers.InterfaceOpts{SubnetID: subnetID}).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Interface added to router %s: SubnetID [%s] PortID [%s]", routerID, ir.SubnetID, ir.PortID)
|
||||
}
|
||||
|
||||
func removeInterface(t *testing.T, routerID, subnetID string) {
|
||||
ir, err := routers.RemoveInterface(base.Client, routerID, routers.InterfaceOpts{SubnetID: subnetID}).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Interface %s removed from %s", ir.ID, routerID)
|
||||
}
|
||||
|
||||
func deleteRouter(t *testing.T, routerID string) {
|
||||
t.Logf("Deleting router %s", routerID)
|
||||
|
||||
res := routers.Delete(base.Client, routerID)
|
||||
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}
|
||||
|
||||
func createFloatingIP(t *testing.T, networkID, portID string) string {
|
||||
t.Logf("Creating floating IP on network [%s] with port [%s]", networkID, portID)
|
||||
|
||||
opts := floatingips.CreateOpts{
|
||||
FloatingNetworkID: networkID,
|
||||
PortID: portID,
|
||||
}
|
||||
|
||||
ip, err := floatingips.Create(base.Client, opts).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Floating IP created: ID [%s] Status [%s] Fixed (internal) IP: [%s] Floating (external) IP: [%s]",
|
||||
ip.ID, ip.Status, ip.FixedIP, ip.FloatingIP)
|
||||
|
||||
return ip.ID
|
||||
}
|
||||
|
||||
func getFloatingIP(t *testing.T, ipID string) {
|
||||
ip, err := floatingips.Get(base.Client, ipID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Getting floating IP: ID [%s] Status [%s]", ip.ID, ip.Status)
|
||||
}
|
||||
|
||||
func updateFloatingIP(t *testing.T, ipID, portID string) {
|
||||
t.Logf("Disassociate all ports from IP %s", ipID)
|
||||
_, err := floatingips.Update(base.Client, ipID, floatingips.UpdateOpts{PortID: ""}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Re-associate the port %s", portID)
|
||||
_, err = floatingips.Update(base.Client, ipID, floatingips.UpdateOpts{PortID: portID}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func deleteFloatingIP(t *testing.T, ipID string) {
|
||||
t.Logf("Deleting IP %s", ipID)
|
||||
res := floatingips.Delete(base.Client, ipID)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
// +build acceptance networking lbaas lbaasmember
|
||||
|
||||
package lbaas
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestMembers(t *testing.T) {
|
||||
base.Setup(t)
|
||||
defer base.Teardown()
|
||||
|
||||
// setup
|
||||
networkID, subnetID := SetupTopology(t)
|
||||
poolID := CreatePool(t, subnetID)
|
||||
|
||||
// create member
|
||||
memberID := createMember(t, poolID)
|
||||
|
||||
// list members
|
||||
listMembers(t)
|
||||
|
||||
// update member
|
||||
updateMember(t, memberID)
|
||||
|
||||
// get member
|
||||
getMember(t, memberID)
|
||||
|
||||
// delete member
|
||||
deleteMember(t, memberID)
|
||||
|
||||
// teardown
|
||||
DeletePool(t, poolID)
|
||||
DeleteTopology(t, networkID)
|
||||
}
|
||||
|
||||
func createMember(t *testing.T, poolID string) string {
|
||||
m, err := members.Create(base.Client, members.CreateOpts{
|
||||
Address: "192.168.199.1",
|
||||
ProtocolPort: 8080,
|
||||
PoolID: poolID,
|
||||
}).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Created member: ID [%s] Status [%s] Weight [%d] Address [%s] Port [%d]",
|
||||
m.ID, m.Status, m.Weight, m.Address, m.ProtocolPort)
|
||||
|
||||
return m.ID
|
||||
}
|
||||
|
||||
func listMembers(t *testing.T) {
|
||||
err := members.List(base.Client, members.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
|
||||
memberList, err := members.ExtractMembers(page)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to extract members: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, m := range memberList {
|
||||
t.Logf("Listing member: ID [%s] Status [%s]", m.ID, m.Status)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func updateMember(t *testing.T, memberID string) {
|
||||
m, err := members.Update(base.Client, memberID, members.UpdateOpts{AdminStateUp: true}).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Updated member ID [%s]", m.ID)
|
||||
}
|
||||
|
||||
func getMember(t *testing.T, memberID string) {
|
||||
m, err := members.Get(base.Client, memberID).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Getting member ID [%s]", m.ID)
|
||||
}
|
||||
|
||||
func deleteMember(t *testing.T, memberID string) {
|
||||
res := members.Delete(base.Client, memberID)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
t.Logf("Deleted member %s", memberID)
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
// +build acceptance networking lbaas lbaasmonitor
|
||||
|
||||
package lbaas
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestMonitors(t *testing.T) {
|
||||
base.Setup(t)
|
||||
defer base.Teardown()
|
||||
|
||||
// create monitor
|
||||
monitorID := CreateMonitor(t)
|
||||
|
||||
// list monitors
|
||||
listMonitors(t)
|
||||
|
||||
// update monitor
|
||||
updateMonitor(t, monitorID)
|
||||
|
||||
// get monitor
|
||||
getMonitor(t, monitorID)
|
||||
|
||||
// delete monitor
|
||||
deleteMonitor(t, monitorID)
|
||||
}
|
||||
|
||||
func listMonitors(t *testing.T) {
|
||||
err := monitors.List(base.Client, monitors.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
|
||||
monitorList, err := monitors.ExtractMonitors(page)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to extract monitors: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, m := range monitorList {
|
||||
t.Logf("Listing monitor: ID [%s] Type [%s] Delay [%ds] Timeout [%d] Retries [%d] Status [%s]",
|
||||
m.ID, m.Type, m.Delay, m.Timeout, m.MaxRetries, m.Status)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func updateMonitor(t *testing.T, monitorID string) {
|
||||
opts := monitors.UpdateOpts{Delay: 10, Timeout: 10, MaxRetries: 3}
|
||||
m, err := monitors.Update(base.Client, monitorID, opts).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Updated monitor ID [%s]", m.ID)
|
||||
}
|
||||
|
||||
func getMonitor(t *testing.T, monitorID string) {
|
||||
m, err := monitors.Get(base.Client, monitorID).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Getting monitor ID [%s]: URL path [%s] HTTP Method [%s] Accepted codes [%s]",
|
||||
m.ID, m.URLPath, m.HTTPMethod, m.ExpectedCodes)
|
||||
}
|
||||
|
||||
func deleteMonitor(t *testing.T, monitorID string) {
|
||||
res := monitors.Delete(base.Client, monitorID)
|
||||
|
||||
th.AssertNoErr(t, res.Err)
|
||||
|
||||
t.Logf("Deleted monitor %s", monitorID)
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
// +build acceptance networking lbaas lbaaspool
|
||||
|
||||
package lbaas
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestPools(t *testing.T) {
|
||||
base.Setup(t)
|
||||
defer base.Teardown()
|
||||
|
||||
// setup
|
||||
networkID, subnetID := SetupTopology(t)
|
||||
|
||||
// create pool
|
||||
poolID := CreatePool(t, subnetID)
|
||||
|
||||
// list pools
|
||||
listPools(t)
|
||||
|
||||
// update pool
|
||||
updatePool(t, poolID)
|
||||
|
||||
// get pool
|
||||
getPool(t, poolID)
|
||||
|
||||
// create monitor
|
||||
monitorID := CreateMonitor(t)
|
||||
|
||||
// associate health monitor
|
||||
associateMonitor(t, poolID, monitorID)
|
||||
|
||||
// disassociate health monitor
|
||||
disassociateMonitor(t, poolID, monitorID)
|
||||
|
||||
// delete pool
|
||||
DeletePool(t, poolID)
|
||||
|
||||
// teardown
|
||||
DeleteTopology(t, networkID)
|
||||
}
|
||||
|
||||
func listPools(t *testing.T) {
|
||||
err := pools.List(base.Client, pools.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
|
||||
poolList, err := pools.ExtractPools(page)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to extract pools: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, p := range poolList {
|
||||
t.Logf("Listing pool: ID [%s] Name [%s] Status [%s] LB algorithm [%s]", p.ID, p.Name, p.Status, p.LBMethod)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func updatePool(t *testing.T, poolID string) {
|
||||
opts := pools.UpdateOpts{Name: "SuperPool", LBMethod: pools.LBMethodLeastConnections}
|
||||
p, err := pools.Update(base.Client, poolID, opts).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Updated pool ID [%s]", p.ID)
|
||||
}
|
||||
|
||||
func getPool(t *testing.T, poolID string) {
|
||||
p, err := pools.Get(base.Client, poolID).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Getting pool ID [%s]", p.ID)
|
||||
}
|
||||
|
||||
func associateMonitor(t *testing.T, poolID, monitorID string) {
|
||||
res := pools.AssociateMonitor(base.Client, poolID, monitorID)
|
||||
|
||||
th.AssertNoErr(t, res.Err)
|
||||
|
||||
t.Logf("Associated pool %s with monitor %s", poolID, monitorID)
|
||||
}
|
||||
|
||||
func disassociateMonitor(t *testing.T, poolID, monitorID string) {
|
||||
res := pools.DisassociateMonitor(base.Client, poolID, monitorID)
|
||||
|
||||
th.AssertNoErr(t, res.Err)
|
||||
|
||||
t.Logf("Disassociated pool %s with monitor %s", poolID, monitorID)
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
// +build acceptance networking lbaas lbaasvip
|
||||
|
||||
package lbaas
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestVIPs(t *testing.T) {
|
||||
base.Setup(t)
|
||||
defer base.Teardown()
|
||||
|
||||
// setup
|
||||
networkID, subnetID := SetupTopology(t)
|
||||
poolID := CreatePool(t, subnetID)
|
||||
|
||||
// create VIP
|
||||
VIPID := createVIP(t, subnetID, poolID)
|
||||
|
||||
// list VIPs
|
||||
listVIPs(t)
|
||||
|
||||
// update VIP
|
||||
updateVIP(t, VIPID)
|
||||
|
||||
// get VIP
|
||||
getVIP(t, VIPID)
|
||||
|
||||
// delete VIP
|
||||
deleteVIP(t, VIPID)
|
||||
|
||||
// teardown
|
||||
DeletePool(t, poolID)
|
||||
DeleteTopology(t, networkID)
|
||||
}
|
||||
|
||||
func createVIP(t *testing.T, subnetID, poolID string) string {
|
||||
p, err := vips.Create(base.Client, vips.CreateOpts{
|
||||
Protocol: "HTTP",
|
||||
Name: "New_VIP",
|
||||
AdminStateUp: vips.Up,
|
||||
SubnetID: subnetID,
|
||||
PoolID: poolID,
|
||||
ProtocolPort: 80,
|
||||
}).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Created pool %s", p.ID)
|
||||
|
||||
return p.ID
|
||||
}
|
||||
|
||||
func listVIPs(t *testing.T) {
|
||||
err := vips.List(base.Client, vips.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
|
||||
vipList, err := vips.ExtractVIPs(page)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to extract VIPs: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, vip := range vipList {
|
||||
t.Logf("Listing VIP: ID [%s] Name [%s] Address [%s] Port [%s] Connection Limit [%d]",
|
||||
vip.ID, vip.Name, vip.Address, vip.ProtocolPort, vip.ConnLimit)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func updateVIP(t *testing.T, VIPID string) {
|
||||
i1000 := 1000
|
||||
_, err := vips.Update(base.Client, VIPID, vips.UpdateOpts{ConnLimit: &i1000}).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Updated VIP ID [%s]", VIPID)
|
||||
}
|
||||
|
||||
func getVIP(t *testing.T, VIPID string) {
|
||||
vip, err := vips.Get(base.Client, VIPID).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Getting VIP ID [%s]: Status [%s]", vip.ID, vip.Status)
|
||||
}
|
||||
|
||||
func deleteVIP(t *testing.T, VIPID string) {
|
||||
res := vips.Delete(base.Client, VIPID)
|
||||
|
||||
th.AssertNoErr(t, res.Err)
|
||||
|
||||
t.Logf("Deleted VIP %s", VIPID)
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
// +build acceptance networking
|
||||
|
||||
package extensions
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestNetworkCRUDOperations(t *testing.T) {
|
||||
base.Setup(t)
|
||||
defer base.Teardown()
|
||||
|
||||
// Create a network
|
||||
n, err := networks.Create(base.Client, networks.CreateOpts{Name: "sample_network", AdminStateUp: networks.Up}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.AssertEquals(t, n.Name, "sample_network")
|
||||
th.AssertEquals(t, n.AdminStateUp, true)
|
||||
networkID := n.ID
|
||||
|
||||
// List networks
|
||||
pager := networks.List(base.Client, networks.ListOpts{Limit: 2})
|
||||
err = pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
t.Logf("--- Page ---")
|
||||
|
||||
networkList, err := networks.ExtractNetworks(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, n := range networkList {
|
||||
t.Logf("Network: ID [%s] Name [%s] Status [%s] Is shared? [%s]",
|
||||
n.ID, n.Name, n.Status, strconv.FormatBool(n.Shared))
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.CheckNoErr(t, err)
|
||||
|
||||
// Get a network
|
||||
if networkID == "" {
|
||||
t.Fatalf("In order to retrieve a network, the NetworkID must be set")
|
||||
}
|
||||
n, err = networks.Get(base.Client, networkID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.AssertEquals(t, n.Status, "ACTIVE")
|
||||
th.AssertDeepEquals(t, n.Subnets, []string{})
|
||||
th.AssertEquals(t, n.Name, "sample_network")
|
||||
th.AssertEquals(t, n.AdminStateUp, true)
|
||||
th.AssertEquals(t, n.Shared, false)
|
||||
th.AssertEquals(t, n.ID, networkID)
|
||||
|
||||
// Update network
|
||||
n, err = networks.Update(base.Client, networkID, networks.UpdateOpts{Name: "new_network_name"}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.AssertEquals(t, n.Name, "new_network_name")
|
||||
|
||||
// Delete network
|
||||
res := networks.Delete(base.Client, networkID)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}
|
||||
|
||||
func TestCreateMultipleNetworks(t *testing.T) {
|
||||
//networks.CreateMany()
|
||||
}
|
|
@ -1,171 +0,0 @@
|
|||
// +build acceptance networking security
|
||||
|
||||
package extensions
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/ports"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestSecurityGroups(t *testing.T) {
|
||||
base.Setup(t)
|
||||
defer base.Teardown()
|
||||
|
||||
// create security group
|
||||
groupID := createSecGroup(t)
|
||||
|
||||
// delete security group
|
||||
defer deleteSecGroup(t, groupID)
|
||||
|
||||
// list security group
|
||||
listSecGroups(t)
|
||||
|
||||
// get security group
|
||||
getSecGroup(t, groupID)
|
||||
|
||||
// create port with security group
|
||||
networkID, portID := createPort(t, groupID)
|
||||
|
||||
// teardown
|
||||
defer deleteNetwork(t, networkID)
|
||||
|
||||
// delete port
|
||||
defer deletePort(t, portID)
|
||||
}
|
||||
|
||||
func TestSecurityGroupRules(t *testing.T) {
|
||||
base.Setup(t)
|
||||
defer base.Teardown()
|
||||
|
||||
// create security group
|
||||
groupID := createSecGroup(t)
|
||||
|
||||
defer deleteSecGroup(t, groupID)
|
||||
|
||||
// create security group rule
|
||||
ruleID := createSecRule(t, groupID)
|
||||
|
||||
// delete security group rule
|
||||
defer deleteSecRule(t, ruleID)
|
||||
|
||||
// list security group rule
|
||||
listSecRules(t)
|
||||
|
||||
// get security group rule
|
||||
getSecRule(t, ruleID)
|
||||
}
|
||||
|
||||
func createSecGroup(t *testing.T) string {
|
||||
sg, err := groups.Create(base.Client, groups.CreateOpts{
|
||||
Name: "new-webservers",
|
||||
Description: "security group for webservers",
|
||||
}).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Created security group %s", sg.ID)
|
||||
|
||||
return sg.ID
|
||||
}
|
||||
|
||||
func listSecGroups(t *testing.T) {
|
||||
err := groups.List(base.Client, groups.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
|
||||
list, err := groups.ExtractGroups(page)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to extract secgroups: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, sg := range list {
|
||||
t.Logf("Listing security group: ID [%s] Name [%s]", sg.ID, sg.Name)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func getSecGroup(t *testing.T, id string) {
|
||||
sg, err := groups.Get(base.Client, id).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Getting security group: ID [%s] Name [%s] Description [%s]", sg.ID, sg.Name, sg.Description)
|
||||
}
|
||||
|
||||
func createPort(t *testing.T, groupID string) (string, string) {
|
||||
n, err := networks.Create(base.Client, networks.CreateOpts{Name: "tmp_network"}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Created network %s", n.ID)
|
||||
|
||||
opts := ports.CreateOpts{
|
||||
NetworkID: n.ID,
|
||||
Name: "my_port",
|
||||
SecurityGroups: []string{groupID},
|
||||
}
|
||||
p, err := ports.Create(base.Client, opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Created port %s with security group %s", p.ID, groupID)
|
||||
|
||||
return n.ID, p.ID
|
||||
}
|
||||
|
||||
func deleteSecGroup(t *testing.T, groupID string) {
|
||||
res := groups.Delete(base.Client, groupID)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
t.Logf("Deleted security group %s", groupID)
|
||||
}
|
||||
|
||||
func createSecRule(t *testing.T, groupID string) string {
|
||||
r, err := rules.Create(base.Client, rules.CreateOpts{
|
||||
Direction: "ingress",
|
||||
PortRangeMin: 80,
|
||||
EtherType: "IPv4",
|
||||
PortRangeMax: 80,
|
||||
Protocol: "tcp",
|
||||
SecGroupID: groupID,
|
||||
}).Extract()
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Created security group rule %s", r.ID)
|
||||
|
||||
return r.ID
|
||||
}
|
||||
|
||||
func listSecRules(t *testing.T) {
|
||||
err := rules.List(base.Client, rules.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
|
||||
list, err := rules.ExtractRules(page)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to extract sec rules: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, r := range list {
|
||||
t.Logf("Listing security rule: ID [%s]", r.ID)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func getSecRule(t *testing.T, id string) {
|
||||
r, err := rules.Get(base.Client, id).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Getting security rule: ID [%s] Direction [%s] EtherType [%s] Protocol [%s]",
|
||||
r.ID, r.Direction, r.EtherType, r.Protocol)
|
||||
}
|
||||
|
||||
func deleteSecRule(t *testing.T, id string) {
|
||||
res := rules.Delete(base.Client, id)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
t.Logf("Deleted security rule %s", id)
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
// +build acceptance networking
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestNetworkCRUDOperations(t *testing.T) {
|
||||
Setup(t)
|
||||
defer Teardown()
|
||||
|
||||
// Create a network
|
||||
n, err := networks.Create(Client, networks.CreateOpts{Name: "sample_network", AdminStateUp: networks.Up}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
defer networks.Delete(Client, n.ID)
|
||||
th.AssertEquals(t, n.Name, "sample_network")
|
||||
th.AssertEquals(t, n.AdminStateUp, true)
|
||||
networkID := n.ID
|
||||
|
||||
// List networks
|
||||
pager := networks.List(Client, networks.ListOpts{Limit: 2})
|
||||
err = pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
t.Logf("--- Page ---")
|
||||
|
||||
networkList, err := networks.ExtractNetworks(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, n := range networkList {
|
||||
t.Logf("Network: ID [%s] Name [%s] Status [%s] Is shared? [%s]",
|
||||
n.ID, n.Name, n.Status, strconv.FormatBool(n.Shared))
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.CheckNoErr(t, err)
|
||||
|
||||
// Get a network
|
||||
if networkID == "" {
|
||||
t.Fatalf("In order to retrieve a network, the NetworkID must be set")
|
||||
}
|
||||
n, err = networks.Get(Client, networkID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.AssertEquals(t, n.Status, "ACTIVE")
|
||||
th.AssertDeepEquals(t, n.Subnets, []string{})
|
||||
th.AssertEquals(t, n.Name, "sample_network")
|
||||
th.AssertEquals(t, n.AdminStateUp, true)
|
||||
th.AssertEquals(t, n.Shared, false)
|
||||
th.AssertEquals(t, n.ID, networkID)
|
||||
|
||||
// Update network
|
||||
n, err = networks.Update(Client, networkID, networks.UpdateOpts{Name: "new_network_name"}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.AssertEquals(t, n.Name, "new_network_name")
|
||||
|
||||
// Delete network
|
||||
res := networks.Delete(Client, networkID)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}
|
||||
|
||||
func TestCreateMultipleNetworks(t *testing.T) {
|
||||
//networks.CreateMany()
|
||||
}
|
117
vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/port_test.go
generated
vendored
117
vendor/github.com/rackspace/gophercloud/acceptance/openstack/networking/v2/port_test.go
generated
vendored
|
@ -1,117 +0,0 @@
|
|||
// +build acceptance networking
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/ports"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/subnets"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestPortCRUD(t *testing.T) {
|
||||
Setup(t)
|
||||
defer Teardown()
|
||||
|
||||
// Setup network
|
||||
t.Log("Setting up network")
|
||||
networkID, err := createNetwork()
|
||||
th.AssertNoErr(t, err)
|
||||
defer networks.Delete(Client, networkID)
|
||||
|
||||
// Setup subnet
|
||||
t.Logf("Setting up subnet on network %s", networkID)
|
||||
subnetID, err := createSubnet(networkID)
|
||||
th.AssertNoErr(t, err)
|
||||
defer subnets.Delete(Client, subnetID)
|
||||
|
||||
// Create port
|
||||
t.Logf("Create port based on subnet %s", subnetID)
|
||||
portID := createPort(t, networkID, subnetID)
|
||||
|
||||
// List ports
|
||||
t.Logf("Listing all ports")
|
||||
listPorts(t)
|
||||
|
||||
// Get port
|
||||
if portID == "" {
|
||||
t.Fatalf("In order to retrieve a port, the portID must be set")
|
||||
}
|
||||
p, err := ports.Get(Client, portID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.AssertEquals(t, p.ID, portID)
|
||||
|
||||
// Update port
|
||||
p, err = ports.Update(Client, portID, ports.UpdateOpts{Name: "new_port_name"}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.AssertEquals(t, p.Name, "new_port_name")
|
||||
|
||||
// Delete port
|
||||
res := ports.Delete(Client, portID)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}
|
||||
|
||||
func createPort(t *testing.T, networkID, subnetID string) string {
|
||||
enable := false
|
||||
opts := ports.CreateOpts{
|
||||
NetworkID: networkID,
|
||||
Name: "my_port",
|
||||
AdminStateUp: &enable,
|
||||
FixedIPs: []ports.IP{ports.IP{SubnetID: subnetID}},
|
||||
}
|
||||
p, err := ports.Create(Client, opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.AssertEquals(t, p.NetworkID, networkID)
|
||||
th.AssertEquals(t, p.Name, "my_port")
|
||||
th.AssertEquals(t, p.AdminStateUp, false)
|
||||
|
||||
return p.ID
|
||||
}
|
||||
|
||||
func listPorts(t *testing.T) {
|
||||
count := 0
|
||||
pager := ports.List(Client, ports.ListOpts{})
|
||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
count++
|
||||
t.Logf("--- Page ---")
|
||||
|
||||
portList, err := ports.ExtractPorts(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, p := range portList {
|
||||
t.Logf("Port: ID [%s] Name [%s] Status [%s] MAC addr [%s] Fixed IPs [%#v] Security groups [%#v]",
|
||||
p.ID, p.Name, p.Status, p.MACAddress, p.FixedIPs, p.SecurityGroups)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
th.CheckNoErr(t, err)
|
||||
|
||||
if count == 0 {
|
||||
t.Logf("No pages were iterated over when listing ports")
|
||||
}
|
||||
}
|
||||
|
||||
func createNetwork() (string, error) {
|
||||
res, err := networks.Create(Client, networks.CreateOpts{Name: "tmp_network", AdminStateUp: networks.Up}).Extract()
|
||||
return res.ID, err
|
||||
}
|
||||
|
||||
func createSubnet(networkID string) (string, error) {
|
||||
s, err := subnets.Create(Client, subnets.CreateOpts{
|
||||
NetworkID: networkID,
|
||||
CIDR: "192.168.199.0/24",
|
||||
IPVersion: subnets.IPv4,
|
||||
Name: "my_subnet",
|
||||
EnableDHCP: subnets.Down,
|
||||
}).Extract()
|
||||
return s.ID, err
|
||||
}
|
||||
|
||||
func TestPortBatchCreate(t *testing.T) {
|
||||
// todo
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
// +build acceptance networking
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/subnets"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
Setup(t)
|
||||
defer Teardown()
|
||||
|
||||
pager := subnets.List(Client, subnets.ListOpts{Limit: 2})
|
||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
t.Logf("--- Page ---")
|
||||
|
||||
subnetList, err := subnets.ExtractSubnets(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, s := range subnetList {
|
||||
t.Logf("Subnet: ID [%s] Name [%s] IP Version [%d] CIDR [%s] GatewayIP [%s]",
|
||||
s.ID, s.Name, s.IPVersion, s.CIDR, s.GatewayIP)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.CheckNoErr(t, err)
|
||||
}
|
||||
|
||||
func TestCRUD(t *testing.T) {
|
||||
Setup(t)
|
||||
defer Teardown()
|
||||
|
||||
// Setup network
|
||||
t.Log("Setting up network")
|
||||
n, err := networks.Create(Client, networks.CreateOpts{Name: "tmp_network", AdminStateUp: networks.Up}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
networkID := n.ID
|
||||
defer networks.Delete(Client, networkID)
|
||||
|
||||
// Create subnet
|
||||
t.Log("Create subnet")
|
||||
enable := false
|
||||
opts := subnets.CreateOpts{
|
||||
NetworkID: networkID,
|
||||
CIDR: "192.168.199.0/24",
|
||||
IPVersion: subnets.IPv4,
|
||||
Name: "my_subnet",
|
||||
EnableDHCP: &enable,
|
||||
}
|
||||
s, err := subnets.Create(Client, opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
th.AssertEquals(t, s.NetworkID, networkID)
|
||||
th.AssertEquals(t, s.CIDR, "192.168.199.0/24")
|
||||
th.AssertEquals(t, s.IPVersion, 4)
|
||||
th.AssertEquals(t, s.Name, "my_subnet")
|
||||
th.AssertEquals(t, s.EnableDHCP, false)
|
||||
subnetID := s.ID
|
||||
|
||||
// Get subnet
|
||||
t.Log("Getting subnet")
|
||||
s, err = subnets.Get(Client, subnetID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.AssertEquals(t, s.ID, subnetID)
|
||||
|
||||
// Update subnet
|
||||
t.Log("Update subnet")
|
||||
s, err = subnets.Update(Client, subnetID, subnets.UpdateOpts{Name: "new_subnet_name"}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.AssertEquals(t, s.Name, "new_subnet_name")
|
||||
|
||||
// Delete subnet
|
||||
t.Log("Delete subnet")
|
||||
res := subnets.Delete(Client, subnetID)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}
|
||||
|
||||
func TestBatchCreate(t *testing.T) {
|
||||
// todo
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestAccounts(t *testing.T) {
|
||||
// Create a provider client for making the HTTP requests.
|
||||
// See common.go in this directory for more information.
|
||||
client := newClient(t)
|
||||
|
||||
// Update an account's metadata.
|
||||
updateres := accounts.Update(client, accounts.UpdateOpts{Metadata: metadata})
|
||||
t.Logf("Update Account Response: %+v\n", updateres)
|
||||
updateHeaders, err := updateres.Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Update Account Response Headers: %+v\n", updateHeaders)
|
||||
|
||||
// Defer the deletion of the metadata set above.
|
||||
defer func() {
|
||||
tempMap := make(map[string]string)
|
||||
for k := range metadata {
|
||||
tempMap[k] = ""
|
||||
}
|
||||
updateres = accounts.Update(client, accounts.UpdateOpts{Metadata: tempMap})
|
||||
th.AssertNoErr(t, updateres.Err)
|
||||
}()
|
||||
|
||||
// Extract the custom metadata from the 'Get' response.
|
||||
res := accounts.Get(client, nil)
|
||||
|
||||
h, err := res.Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Get Account Response Headers: %+v\n", h)
|
||||
|
||||
am, err := res.ExtractMetadata()
|
||||
th.AssertNoErr(t, err)
|
||||
for k := range metadata {
|
||||
if am[k] != metadata[strings.Title(k)] {
|
||||
t.Errorf("Expected custom metadata with key: %s", k)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||
"github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
// numContainers is the number of containers to create for testing.
|
||||
var numContainers = 2
|
||||
|
||||
func TestContainers(t *testing.T) {
|
||||
// Create a new client to execute the HTTP requests. See common.go for newClient body.
|
||||
client := newClient(t)
|
||||
|
||||
// Create a slice of random container names.
|
||||
cNames := make([]string, numContainers)
|
||||
for i := 0; i < numContainers; i++ {
|
||||
cNames[i] = tools.RandomString("gophercloud-test-container-", 8)
|
||||
}
|
||||
|
||||
// Create numContainers containers.
|
||||
for i := 0; i < len(cNames); i++ {
|
||||
res := containers.Create(client, cNames[i], nil)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}
|
||||
// Delete the numContainers containers after function completion.
|
||||
defer func() {
|
||||
for i := 0; i < len(cNames); i++ {
|
||||
res := containers.Delete(client, cNames[i])
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}
|
||||
}()
|
||||
|
||||
// List the numContainer names that were just created. To just list those,
|
||||
// the 'prefix' parameter is used.
|
||||
err := containers.List(client, &containers.ListOpts{Full: true, Prefix: "gophercloud-test-container-"}).EachPage(func(page pagination.Page) (bool, error) {
|
||||
containerList, err := containers.ExtractInfo(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, n := range containerList {
|
||||
t.Logf("Container: Name [%s] Count [%d] Bytes [%d]",
|
||||
n.Name, n.Count, n.Bytes)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
// List the info for the numContainer containers that were created.
|
||||
err = containers.List(client, &containers.ListOpts{Full: false, Prefix: "gophercloud-test-container-"}).EachPage(func(page pagination.Page) (bool, error) {
|
||||
containerList, err := containers.ExtractNames(page)
|
||||
th.AssertNoErr(t, err)
|
||||
for _, n := range containerList {
|
||||
t.Logf("Container: Name [%s]", n)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
// Update one of the numContainer container metadata.
|
||||
updateres := containers.Update(client, cNames[0], &containers.UpdateOpts{Metadata: metadata})
|
||||
th.AssertNoErr(t, updateres.Err)
|
||||
// After the tests are done, delete the metadata that was set.
|
||||
defer func() {
|
||||
tempMap := make(map[string]string)
|
||||
for k := range metadata {
|
||||
tempMap[k] = ""
|
||||
}
|
||||
res := containers.Update(client, cNames[0], &containers.UpdateOpts{Metadata: tempMap})
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}()
|
||||
|
||||
// Retrieve a container's metadata.
|
||||
cm, err := containers.Get(client, cNames[0]).ExtractMetadata()
|
||||
th.AssertNoErr(t, err)
|
||||
for k := range metadata {
|
||||
if cm[k] != metadata[strings.Title(k)] {
|
||||
t.Errorf("Expected custom metadata with key: %s", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestListAllContainers(t *testing.T) {
|
||||
// Create a new client to execute the HTTP requests. See common.go for newClient body.
|
||||
client := newClient(t)
|
||||
|
||||
numContainers := 20
|
||||
|
||||
// Create a slice of random container names.
|
||||
cNames := make([]string, numContainers)
|
||||
for i := 0; i < numContainers; i++ {
|
||||
cNames[i] = tools.RandomString("gophercloud-test-container-", 8)
|
||||
}
|
||||
|
||||
// Create numContainers containers.
|
||||
for i := 0; i < len(cNames); i++ {
|
||||
res := containers.Create(client, cNames[i], nil)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}
|
||||
// Delete the numContainers containers after function completion.
|
||||
defer func() {
|
||||
for i := 0; i < len(cNames); i++ {
|
||||
res := containers.Delete(client, cNames[i])
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}
|
||||
}()
|
||||
|
||||
// List all the numContainer names that were just created. To just list those,
|
||||
// the 'prefix' parameter is used.
|
||||
allPages, err := containers.List(client, &containers.ListOpts{Full: true, Limit: 5, Prefix: "gophercloud-test-container-"}).AllPages()
|
||||
th.AssertNoErr(t, err)
|
||||
containerInfoList, err := containers.ExtractInfo(allPages)
|
||||
th.AssertNoErr(t, err)
|
||||
for _, n := range containerInfoList {
|
||||
t.Logf("Container: Name [%s] Count [%d] Bytes [%d]",
|
||||
n.Name, n.Count, n.Bytes)
|
||||
}
|
||||
th.AssertEquals(t, numContainers, len(containerInfoList))
|
||||
|
||||
// List the info for all the numContainer containers that were created.
|
||||
allPages, err = containers.List(client, &containers.ListOpts{Full: false, Limit: 2, Prefix: "gophercloud-test-container-"}).AllPages()
|
||||
th.AssertNoErr(t, err)
|
||||
containerNamesList, err := containers.ExtractNames(allPages)
|
||||
th.AssertNoErr(t, err)
|
||||
for _, n := range containerNamesList {
|
||||
t.Logf("Container: Name [%s]", n)
|
||||
}
|
||||
th.AssertEquals(t, numContainers, len(containerNamesList))
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/acceptance/tools"
|
||||
"github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers"
|
||||
"github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
// numObjects is the number of objects to create for testing.
|
||||
var numObjects = 2
|
||||
|
||||
func TestObjects(t *testing.T) {
|
||||
// Create a provider client for executing the HTTP request.
|
||||
// See common.go for more information.
|
||||
client := newClient(t)
|
||||
|
||||
// Make a slice of length numObjects to hold the random object names.
|
||||
oNames := make([]string, numObjects)
|
||||
for i := 0; i < len(oNames); i++ {
|
||||
oNames[i] = tools.RandomString("test-object-", 8)
|
||||
}
|
||||
|
||||
// Create a container to hold the test objects.
|
||||
cName := tools.RandomString("test-container-", 8)
|
||||
header, err := containers.Create(client, cName, nil).ExtractHeader()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Create object headers: %+v\n", header)
|
||||
|
||||
// Defer deletion of the container until after testing.
|
||||
defer func() {
|
||||
res := containers.Delete(client, cName)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}()
|
||||
|
||||
// Create a slice of buffers to hold the test object content.
|
||||
oContents := make([]*bytes.Buffer, numObjects)
|
||||
for i := 0; i < numObjects; i++ {
|
||||
oContents[i] = bytes.NewBuffer([]byte(tools.RandomString("", 10)))
|
||||
res := objects.Create(client, cName, oNames[i], oContents[i], nil)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}
|
||||
// Delete the objects after testing.
|
||||
defer func() {
|
||||
for i := 0; i < numObjects; i++ {
|
||||
res := objects.Delete(client, cName, oNames[i], nil)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}
|
||||
}()
|
||||
|
||||
ons := make([]string, 0, len(oNames))
|
||||
err = objects.List(client, cName, &objects.ListOpts{Full: false, Prefix: "test-object-"}).EachPage(func(page pagination.Page) (bool, error) {
|
||||
names, err := objects.ExtractNames(page)
|
||||
th.AssertNoErr(t, err)
|
||||
ons = append(ons, names...)
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
th.AssertEquals(t, len(ons), len(oNames))
|
||||
|
||||
ois := make([]objects.Object, 0, len(oNames))
|
||||
err = objects.List(client, cName, &objects.ListOpts{Full: true, Prefix: "test-object-"}).EachPage(func(page pagination.Page) (bool, error) {
|
||||
info, err := objects.ExtractInfo(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
ois = append(ois, info...)
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
th.AssertEquals(t, len(ois), len(oNames))
|
||||
|
||||
// Copy the contents of one object to another.
|
||||
copyres := objects.Copy(client, cName, oNames[0], &objects.CopyOpts{Destination: cName + "/" + oNames[1]})
|
||||
th.AssertNoErr(t, copyres.Err)
|
||||
|
||||
// Download one of the objects that was created above.
|
||||
o1Content, err := objects.Download(client, cName, oNames[0], nil).ExtractContent()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
// Download the another object that was create above.
|
||||
o2Content, err := objects.Download(client, cName, oNames[1], nil).ExtractContent()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
// Compare the two object's contents to test that the copy worked.
|
||||
th.AssertEquals(t, string(o2Content), string(o1Content))
|
||||
|
||||
// Update an object's metadata.
|
||||
updateres := objects.Update(client, cName, oNames[0], &objects.UpdateOpts{Metadata: metadata})
|
||||
th.AssertNoErr(t, updateres.Err)
|
||||
|
||||
// Delete the object's metadata after testing.
|
||||
defer func() {
|
||||
tempMap := make(map[string]string)
|
||||
for k := range metadata {
|
||||
tempMap[k] = ""
|
||||
}
|
||||
res := objects.Update(client, cName, oNames[0], &objects.UpdateOpts{Metadata: tempMap})
|
||||
th.AssertNoErr(t, res.Err)
|
||||
}()
|
||||
|
||||
// Retrieve an object's metadata.
|
||||
om, err := objects.Get(client, cName, oNames[0], nil).ExtractMetadata()
|
||||
th.AssertNoErr(t, err)
|
||||
for k := range metadata {
|
||||
if om[k] != metadata[strings.Title(k)] {
|
||||
t.Errorf("Expected custom metadata with key: %s", k)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestBuildInfo(t *testing.T) {
|
||||
// Create a provider client for making the HTTP requests.
|
||||
// See common.go in this directory for more information.
|
||||
client := newClient(t)
|
||||
|
||||
bi, err := buildinfo.Get(client).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("retrieved build info: %+v\n", bi)
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents"
|
||||
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestStackEvents(t *testing.T) {
|
||||
// Create a provider client for making the HTTP requests.
|
||||
// See common.go in this directory for more information.
|
||||
client := newClient(t)
|
||||
|
||||
stackName := "postman_stack_2"
|
||||
resourceName := "hello_world"
|
||||
var eventID string
|
||||
|
||||
createOpts := stacks.CreateOpts{
|
||||
Name: stackName,
|
||||
Template: template,
|
||||
Timeout: 5,
|
||||
}
|
||||
stack, err := stacks.Create(client, createOpts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Created stack: %+v\n", stack)
|
||||
defer func() {
|
||||
err := stacks.Delete(client, stackName, stack.ID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Deleted stack (%s)", stackName)
|
||||
}()
|
||||
err = gophercloud.WaitFor(60, func() (bool, error) {
|
||||
getStack, err := stacks.Get(client, stackName, stack.ID).Extract()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if getStack.Status == "CREATE_COMPLETE" {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
|
||||
err = stackevents.List(client, stackName, stack.ID, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||
events, err := stackevents.ExtractEvents(page)
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("listed events: %+v\n", events)
|
||||
eventID = events[0].ID
|
||||
return false, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
err = stackevents.ListResourceEvents(client, stackName, stack.ID, resourceName, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||
resourceEvents, err := stackevents.ExtractEvents(page)
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("listed resource events: %+v\n", resourceEvents)
|
||||
return false, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
event, err := stackevents.Get(client, stackName, stack.ID, resourceName, eventID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("retrieved event: %+v\n", event)
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources"
|
||||
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestStackResources(t *testing.T) {
|
||||
// Create a provider client for making the HTTP requests.
|
||||
// See common.go in this directory for more information.
|
||||
client := newClient(t)
|
||||
|
||||
stackName := "postman_stack_2"
|
||||
|
||||
createOpts := stacks.CreateOpts{
|
||||
Name: stackName,
|
||||
Template: template,
|
||||
Timeout: 5,
|
||||
}
|
||||
stack, err := stacks.Create(client, createOpts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Created stack: %+v\n", stack)
|
||||
defer func() {
|
||||
err := stacks.Delete(client, stackName, stack.ID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Deleted stack (%s)", stackName)
|
||||
}()
|
||||
err = gophercloud.WaitFor(60, func() (bool, error) {
|
||||
getStack, err := stacks.Get(client, stackName, stack.ID).Extract()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if getStack.Status == "CREATE_COMPLETE" {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
|
||||
resourceName := "hello_world"
|
||||
resource, err := stackresources.Get(client, stackName, stack.ID, resourceName).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Got stack resource: %+v\n", resource)
|
||||
|
||||
metadata, err := stackresources.Metadata(client, stackName, stack.ID, resourceName).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Got stack resource metadata: %+v\n", metadata)
|
||||
|
||||
err = stackresources.List(client, stackName, stack.ID, stackresources.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
|
||||
resources, err := stackresources.ExtractResources(page)
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("resources: %+v\n", resources)
|
||||
return false, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestStacks(t *testing.T) {
|
||||
// Create a provider client for making the HTTP requests.
|
||||
// See common.go in this directory for more information.
|
||||
client := newClient(t)
|
||||
|
||||
stackName1 := "gophercloud-test-stack-2"
|
||||
createOpts := stacks.CreateOpts{
|
||||
Name: stackName1,
|
||||
Template: template,
|
||||
Timeout: 5,
|
||||
}
|
||||
stack, err := stacks.Create(client, createOpts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Created stack: %+v\n", stack)
|
||||
defer func() {
|
||||
err := stacks.Delete(client, stackName1, stack.ID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Deleted stack (%s)", stackName1)
|
||||
}()
|
||||
err = gophercloud.WaitFor(60, func() (bool, error) {
|
||||
getStack, err := stacks.Get(client, stackName1, stack.ID).Extract()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if getStack.Status == "CREATE_COMPLETE" {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
|
||||
updateOpts := stacks.UpdateOpts{
|
||||
Template: template,
|
||||
Timeout: 20,
|
||||
}
|
||||
err = stacks.Update(client, stackName1, stack.ID, updateOpts).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
err = gophercloud.WaitFor(60, func() (bool, error) {
|
||||
getStack, err := stacks.Get(client, stackName1, stack.ID).Extract()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if getStack.Status == "UPDATE_COMPLETE" {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
|
||||
t.Logf("Updated stack")
|
||||
|
||||
err = stacks.List(client, nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||
stackList, err := stacks.ExtractStacks(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
t.Logf("Got stack list: %+v\n", stackList)
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
getStack, err := stacks.Get(client, stackName1, stack.ID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Got stack: %+v\n", getStack)
|
||||
|
||||
abandonedStack, err := stacks.Abandon(client, stackName1, stack.ID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Abandonded stack %+v\n", abandonedStack)
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
|
||||
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestStackTemplates(t *testing.T) {
|
||||
// Create a provider client for making the HTTP requests.
|
||||
// See common.go in this directory for more information.
|
||||
client := newClient(t)
|
||||
|
||||
stackName := "postman_stack_2"
|
||||
|
||||
createOpts := stacks.CreateOpts{
|
||||
Name: stackName,
|
||||
Template: template,
|
||||
Timeout: 5,
|
||||
}
|
||||
stack, err := stacks.Create(client, createOpts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Created stack: %+v\n", stack)
|
||||
defer func() {
|
||||
err := stacks.Delete(client, stackName, stack.ID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Deleted stack (%s)", stackName)
|
||||
}()
|
||||
err = gophercloud.WaitFor(60, func() (bool, error) {
|
||||
getStack, err := stacks.Get(client, stackName, stack.ID).Extract()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if getStack.Status == "CREATE_COMPLETE" {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
|
||||
tmpl, err := stacktemplates.Get(client, stackName, stack.ID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("retrieved template: %+v\n", tmpl)
|
||||
|
||||
validateOpts := stacktemplates.ValidateOpts{
|
||||
Template: map[string]interface{}{
|
||||
"heat_template_version": "2013-05-23",
|
||||
"description": "Simple template to test heat commands",
|
||||
"parameters": map[string]interface{}{
|
||||
"flavor": map[string]interface{}{
|
||||
"default": "m1.tiny",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"resources": map[string]interface{}{
|
||||
"hello_world": map[string]interface{}{
|
||||
"type": "OS::Nova::Server",
|
||||
"properties": map[string]interface{}{
|
||||
"key_name": "heat_key",
|
||||
"flavor": map[string]interface{}{
|
||||
"get_param": "flavor",
|
||||
},
|
||||
"image": "ad091b52-742f-469e-8f3c-fd81cadf0743",
|
||||
"user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
validatedTemplate, err := stacktemplates.Validate(client, validateOpts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("validated template: %+v\n", validatedTemplate)
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
// +build acceptance blockstorage snapshots
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
"github.com/rackspace/gophercloud/rackspace/blockstorage/v1/snapshots"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestSnapshots(t *testing.T) {
|
||||
client := setup(t)
|
||||
volID := testVolumeCreate(t, client)
|
||||
|
||||
t.Log("Creating snapshots")
|
||||
s := testSnapshotCreate(t, client, volID)
|
||||
id := s.ID
|
||||
|
||||
t.Log("Listing snapshots")
|
||||
testSnapshotList(t, client)
|
||||
|
||||
t.Logf("Getting snapshot %s", id)
|
||||
testSnapshotGet(t, client, id)
|
||||
|
||||
t.Logf("Updating snapshot %s", id)
|
||||
testSnapshotUpdate(t, client, id)
|
||||
|
||||
t.Logf("Deleting snapshot %s", id)
|
||||
testSnapshotDelete(t, client, id)
|
||||
s.WaitUntilDeleted(client, -1)
|
||||
|
||||
t.Logf("Deleting volume %s", volID)
|
||||
testVolumeDelete(t, client, volID)
|
||||
}
|
||||
|
||||
func testSnapshotCreate(t *testing.T, client *gophercloud.ServiceClient, volID string) *snapshots.Snapshot {
|
||||
opts := snapshots.CreateOpts{VolumeID: volID, Name: "snapshot-001"}
|
||||
s, err := snapshots.Create(client, opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Created snapshot %s", s.ID)
|
||||
|
||||
t.Logf("Waiting for new snapshot to become available...")
|
||||
start := time.Now().Second()
|
||||
s.WaitUntilComplete(client, -1)
|
||||
t.Logf("Snapshot completed after %ds", time.Now().Second()-start)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func testSnapshotList(t *testing.T, client *gophercloud.ServiceClient) {
|
||||
snapshots.List(client).EachPage(func(page pagination.Page) (bool, error) {
|
||||
sList, err := snapshots.ExtractSnapshots(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, s := range sList {
|
||||
t.Logf("Snapshot: ID [%s] Name [%s] Volume ID [%s] Progress [%s] Created [%s]",
|
||||
s.ID, s.Name, s.VolumeID, s.Progress, s.CreatedAt)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
}
|
||||
|
||||
func testSnapshotGet(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||
_, err := snapshots.Get(client, id).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func testSnapshotUpdate(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||
_, err := snapshots.Update(client, id, snapshots.UpdateOpts{Name: "new_name"}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func testSnapshotDelete(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||
res := snapshots.Delete(client, id)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
t.Logf("Deleted snapshot %s", id)
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
// +build acceptance blockstorage volumes
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
"github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestVolumes(t *testing.T) {
|
||||
client := setup(t)
|
||||
|
||||
t.Logf("Listing volumes")
|
||||
testVolumeList(t, client)
|
||||
|
||||
t.Logf("Creating volume")
|
||||
volumeID := testVolumeCreate(t, client)
|
||||
|
||||
t.Logf("Getting volume %s", volumeID)
|
||||
testVolumeGet(t, client, volumeID)
|
||||
|
||||
t.Logf("Updating volume %s", volumeID)
|
||||
testVolumeUpdate(t, client, volumeID)
|
||||
|
||||
t.Logf("Deleting volume %s", volumeID)
|
||||
testVolumeDelete(t, client, volumeID)
|
||||
}
|
||||
|
||||
func testVolumeList(t *testing.T, client *gophercloud.ServiceClient) {
|
||||
volumes.List(client).EachPage(func(page pagination.Page) (bool, error) {
|
||||
vList, err := volumes.ExtractVolumes(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, v := range vList {
|
||||
t.Logf("Volume: ID [%s] Name [%s] Type [%s] Created [%s]", v.ID, v.Name,
|
||||
v.VolumeType, v.CreatedAt)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
}
|
||||
|
||||
func testVolumeCreate(t *testing.T, client *gophercloud.ServiceClient) string {
|
||||
vol, err := volumes.Create(client, os.CreateOpts{Size: 75}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Created volume: ID [%s] Size [%s]", vol.ID, vol.Size)
|
||||
return vol.ID
|
||||
}
|
||||
|
||||
func testVolumeGet(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||
vol, err := volumes.Get(client, id).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Created volume: ID [%s] Size [%s]", vol.ID, vol.Size)
|
||||
}
|
||||
|
||||
func testVolumeUpdate(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||
vol, err := volumes.Update(client, id, volumes.UpdateOpts{Name: "new_name"}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Created volume: ID [%s] Name [%s]", vol.ID, vol.Name)
|
||||
}
|
||||
|
||||
func testVolumeDelete(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||
res := volumes.Delete(client, id)
|
||||
th.AssertNoErr(t, res.Err)
|
||||
t.Logf("Deleted volume %s", id)
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
// +build acceptance blockstorage volumetypes
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
"github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumetypes"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestAll(t *testing.T) {
|
||||
client := setup(t)
|
||||
|
||||
t.Logf("Listing volume types")
|
||||
id := testList(t, client)
|
||||
|
||||
t.Logf("Getting volume type %s", id)
|
||||
testGet(t, client, id)
|
||||
}
|
||||
|
||||
func testList(t *testing.T, client *gophercloud.ServiceClient) string {
|
||||
var lastID string
|
||||
|
||||
volumetypes.List(client).EachPage(func(page pagination.Page) (bool, error) {
|
||||
typeList, err := volumetypes.ExtractVolumeTypes(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, vt := range typeList {
|
||||
t.Logf("Volume type: ID [%s] Name [%s]", vt.ID, vt.Name)
|
||||
lastID = vt.ID
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
return lastID
|
||||
}
|
||||
|
||||
func testGet(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||
vt, err := volumetypes.Get(client, id).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Volume: ID [%s] Name [%s]", vt.ID, vt.Name)
|
||||
}
|
32
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/base_test.go
generated
vendored
32
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/base_test.go
generated
vendored
|
@ -1,32 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/rackspace/cdn/v1/base"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestBaseOps(t *testing.T) {
|
||||
client := newClient(t)
|
||||
t.Log("Retrieving Home Document")
|
||||
testHomeDocumentGet(t, client)
|
||||
|
||||
t.Log("Pinging root URL")
|
||||
testPing(t, client)
|
||||
}
|
||||
|
||||
func testHomeDocumentGet(t *testing.T, client *gophercloud.ServiceClient) {
|
||||
hd, err := base.Get(client).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Retrieved home document: %+v", *hd)
|
||||
}
|
||||
|
||||
func testPing(t *testing.T, client *gophercloud.ServiceClient) {
|
||||
err := base.Ping(client).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Successfully pinged root URL")
|
||||
}
|
47
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/flavor_test.go
generated
vendored
47
vendor/github.com/rackspace/gophercloud/acceptance/rackspace/cdn/v1/flavor_test.go
generated
vendored
|
@ -1,47 +0,0 @@
|
|||
// +build acceptance
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
os "github.com/rackspace/gophercloud/openstack/cdn/v1/flavors"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
"github.com/rackspace/gophercloud/rackspace/cdn/v1/flavors"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestFlavor(t *testing.T) {
|
||||
client := newClient(t)
|
||||
|
||||
t.Log("Listing Flavors")
|
||||
id := testFlavorsList(t, client)
|
||||
|
||||
t.Log("Retrieving Flavor")
|
||||
testFlavorGet(t, client, id)
|
||||
}
|
||||
|
||||
func testFlavorsList(t *testing.T, client *gophercloud.ServiceClient) string {
|
||||
var id string
|
||||
err := flavors.List(client).EachPage(func(page pagination.Page) (bool, error) {
|
||||
flavorList, err := os.ExtractFlavors(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
for _, flavor := range flavorList {
|
||||
t.Logf("Listing flavor: ID [%s] Providers [%+v]", flavor.ID, flavor.Providers)
|
||||
id = flavor.ID
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
return id
|
||||
}
|
||||
|
||||
func testFlavorGet(t *testing.T, client *gophercloud.ServiceClient, id string) {
|
||||
flavor, err := flavors.Get(client, id).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
t.Logf("Retrieved Flavor: %+v", *flavor)
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue