620 lines
15 KiB
Go
620 lines
15 KiB
Go
package godo
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestProjects_List(t *testing.T) {
|
|
setup()
|
|
defer teardown()
|
|
|
|
expectedProjects := []Project{
|
|
{
|
|
ID: "project-1",
|
|
Name: "project-1",
|
|
},
|
|
{
|
|
ID: "project-2",
|
|
Name: "project-2",
|
|
},
|
|
}
|
|
|
|
mux.HandleFunc("/v2/projects", func(w http.ResponseWriter, r *http.Request) {
|
|
testMethod(t, r, http.MethodGet)
|
|
resp, _ := json.Marshal(expectedProjects)
|
|
fmt.Fprint(w, fmt.Sprintf(`{"projects":%s, "meta": {"total": 2}}`, string(resp)))
|
|
})
|
|
|
|
projects, resp, err := client.Projects.List(ctx, nil)
|
|
if err != nil {
|
|
t.Errorf("Projects.List returned error: %v", err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(projects, expectedProjects) {
|
|
t.Errorf("Projects.List returned projects %+v, expected %+v", projects, expectedProjects)
|
|
}
|
|
|
|
expectedMeta := &Meta{Total: 2}
|
|
if !reflect.DeepEqual(resp.Meta, expectedMeta) {
|
|
t.Errorf("Projects.List returned meta %+v, expected %+v", resp.Meta, expectedMeta)
|
|
}
|
|
}
|
|
|
|
func TestProjects_ListWithMultiplePages(t *testing.T) {
|
|
setup()
|
|
defer teardown()
|
|
|
|
mockResp := `
|
|
{
|
|
"projects": [
|
|
{
|
|
"uuid": "project-1",
|
|
"name": "project-1"
|
|
},
|
|
{
|
|
"uuid": "project-2",
|
|
"name": "project-2"
|
|
}
|
|
],
|
|
"links": {
|
|
"pages": {
|
|
"next": "http://example.com/v2/projects?page=2"
|
|
}
|
|
}
|
|
}`
|
|
|
|
mux.HandleFunc("/v2/projects", func(w http.ResponseWriter, r *http.Request) {
|
|
testMethod(t, r, http.MethodGet)
|
|
fmt.Fprint(w, mockResp)
|
|
})
|
|
|
|
_, resp, err := client.Projects.List(ctx, nil)
|
|
if err != nil {
|
|
t.Errorf("Projects.List returned error: %v", err)
|
|
}
|
|
|
|
checkCurrentPage(t, resp, 1)
|
|
}
|
|
|
|
func TestProjects_ListWithPageNumber(t *testing.T) {
|
|
setup()
|
|
defer teardown()
|
|
|
|
mockResp := `
|
|
{
|
|
"projects": [
|
|
{
|
|
"uuid": "project-1",
|
|
"name": "project-1"
|
|
},
|
|
{
|
|
"uuid": "project-2",
|
|
"name": "project-2"
|
|
}
|
|
],
|
|
"links": {
|
|
"pages": {
|
|
"next": "http://example.com/v2/projects?page=3",
|
|
"prev": "http://example.com/v2/projects?page=1",
|
|
"last": "http://example.com/v2/projects?page=3",
|
|
"first": "http://example.com/v2/projects?page=1"
|
|
}
|
|
}
|
|
}`
|
|
|
|
mux.HandleFunc("/v2/projects", func(w http.ResponseWriter, r *http.Request) {
|
|
testMethod(t, r, http.MethodGet)
|
|
fmt.Fprint(w, mockResp)
|
|
})
|
|
|
|
_, resp, err := client.Projects.List(ctx, &ListOptions{Page: 2})
|
|
if err != nil {
|
|
t.Errorf("Projects.List returned error: %v", err)
|
|
}
|
|
|
|
checkCurrentPage(t, resp, 2)
|
|
}
|
|
|
|
func TestProjects_GetDefault(t *testing.T) {
|
|
setup()
|
|
defer teardown()
|
|
|
|
project := &Project{
|
|
ID: "project-1",
|
|
Name: "project-1",
|
|
}
|
|
|
|
mux.HandleFunc("/v2/projects/default", func(w http.ResponseWriter, r *http.Request) {
|
|
testMethod(t, r, http.MethodGet)
|
|
resp, _ := json.Marshal(project)
|
|
fmt.Fprint(w, fmt.Sprintf(`{"project":%s}`, string(resp)))
|
|
})
|
|
|
|
resp, _, err := client.Projects.GetDefault(ctx)
|
|
if err != nil {
|
|
t.Errorf("Projects.GetDefault returned error: %v", err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(resp, project) {
|
|
t.Errorf("Projects.GetDefault returned %+v, expected %+v", resp, project)
|
|
}
|
|
}
|
|
|
|
func TestProjects_GetWithUUID(t *testing.T) {
|
|
setup()
|
|
defer teardown()
|
|
|
|
project := &Project{
|
|
ID: "project-1",
|
|
Name: "project-1",
|
|
}
|
|
|
|
mux.HandleFunc("/v2/projects/project-1", func(w http.ResponseWriter, r *http.Request) {
|
|
testMethod(t, r, http.MethodGet)
|
|
resp, _ := json.Marshal(project)
|
|
fmt.Fprint(w, fmt.Sprintf(`{"project":%s}`, string(resp)))
|
|
})
|
|
|
|
resp, _, err := client.Projects.Get(ctx, "project-1")
|
|
if err != nil {
|
|
t.Errorf("Projects.Get returned error: %v", err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(resp, project) {
|
|
t.Errorf("Projects.Get returned %+v, expected %+v", resp, project)
|
|
}
|
|
}
|
|
|
|
func TestProjects_Create(t *testing.T) {
|
|
setup()
|
|
defer teardown()
|
|
|
|
createRequest := &CreateProjectRequest{
|
|
Name: "my project",
|
|
Description: "for my stuff",
|
|
Purpose: "Just trying out DigitalOcean",
|
|
Environment: "Production",
|
|
}
|
|
|
|
createResp := &Project{
|
|
ID: "project-id",
|
|
Name: createRequest.Name,
|
|
Description: createRequest.Description,
|
|
Purpose: createRequest.Purpose,
|
|
Environment: createRequest.Environment,
|
|
}
|
|
|
|
mux.HandleFunc("/v2/projects", func(w http.ResponseWriter, r *http.Request) {
|
|
v := new(CreateProjectRequest)
|
|
err := json.NewDecoder(r.Body).Decode(v)
|
|
if err != nil {
|
|
t.Fatalf("decode json: %v", err)
|
|
}
|
|
|
|
testMethod(t, r, http.MethodPost)
|
|
if !reflect.DeepEqual(v, createRequest) {
|
|
t.Errorf("Request body = %+v, expected %+v", v, createRequest)
|
|
}
|
|
|
|
resp, _ := json.Marshal(createResp)
|
|
fmt.Fprintf(w, fmt.Sprintf(`{"project":%s}`, string(resp)))
|
|
})
|
|
|
|
project, _, err := client.Projects.Create(ctx, createRequest)
|
|
if err != nil {
|
|
t.Errorf("Projects.Create returned error: %v", err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(project, createResp) {
|
|
t.Errorf("Projects.Create returned %+v, expected %+v", project, createResp)
|
|
}
|
|
}
|
|
|
|
func TestProjects_UpdateWithOneAttribute(t *testing.T) {
|
|
setup()
|
|
defer teardown()
|
|
|
|
updateRequest := &UpdateProjectRequest{
|
|
Name: "my-great-project",
|
|
}
|
|
updateResp := &Project{
|
|
ID: "project-id",
|
|
Name: updateRequest.Name.(string),
|
|
Description: "some-other-description",
|
|
Purpose: "some-other-purpose",
|
|
Environment: "some-other-env",
|
|
IsDefault: false,
|
|
}
|
|
|
|
mux.HandleFunc("/v2/projects/project-1", func(w http.ResponseWriter, r *http.Request) {
|
|
reqBytes, respErr := ioutil.ReadAll(r.Body)
|
|
if respErr != nil {
|
|
t.Error("projects mock didn't work")
|
|
}
|
|
|
|
req := strings.TrimSuffix(string(reqBytes), "\n")
|
|
expectedReq := `{"name":"my-great-project","description":null,"purpose":null,"environment":null,"is_default":null}`
|
|
if req != expectedReq {
|
|
t.Errorf("projects req didn't match up:\n expected %+v\n got %+v\n", expectedReq, req)
|
|
}
|
|
|
|
resp, _ := json.Marshal(updateResp)
|
|
fmt.Fprintf(w, fmt.Sprintf(`{"project":%s}`, string(resp)))
|
|
})
|
|
|
|
project, _, err := client.Projects.Update(ctx, "project-1", updateRequest)
|
|
if err != nil {
|
|
t.Errorf("Projects.Update returned error: %v", err)
|
|
}
|
|
if !reflect.DeepEqual(project, updateResp) {
|
|
t.Errorf("Projects.Update returned %+v, expected %+v", project, updateResp)
|
|
}
|
|
}
|
|
|
|
func TestProjects_UpdateWithAllAttributes(t *testing.T) {
|
|
setup()
|
|
defer teardown()
|
|
|
|
updateRequest := &UpdateProjectRequest{
|
|
Name: "my-great-project",
|
|
Description: "some-description",
|
|
Purpose: "some-purpose",
|
|
Environment: "some-env",
|
|
IsDefault: true,
|
|
}
|
|
updateResp := &Project{
|
|
ID: "project-id",
|
|
Name: updateRequest.Name.(string),
|
|
Description: updateRequest.Description.(string),
|
|
Purpose: updateRequest.Purpose.(string),
|
|
Environment: updateRequest.Environment.(string),
|
|
IsDefault: updateRequest.IsDefault.(bool),
|
|
}
|
|
|
|
mux.HandleFunc("/v2/projects/project-1", func(w http.ResponseWriter, r *http.Request) {
|
|
reqBytes, respErr := ioutil.ReadAll(r.Body)
|
|
if respErr != nil {
|
|
t.Error("projects mock didn't work")
|
|
}
|
|
|
|
req := strings.TrimSuffix(string(reqBytes), "\n")
|
|
expectedReq := `{"name":"my-great-project","description":"some-description","purpose":"some-purpose","environment":"some-env","is_default":true}`
|
|
if req != expectedReq {
|
|
t.Errorf("projects req didn't match up:\n expected %+v\n got %+v\n", expectedReq, req)
|
|
}
|
|
|
|
resp, _ := json.Marshal(updateResp)
|
|
fmt.Fprintf(w, fmt.Sprintf(`{"project":%s}`, string(resp)))
|
|
})
|
|
|
|
project, _, err := client.Projects.Update(ctx, "project-1", updateRequest)
|
|
if err != nil {
|
|
t.Errorf("Projects.Update returned error: %v", err)
|
|
}
|
|
if !reflect.DeepEqual(project, updateResp) {
|
|
t.Errorf("Projects.Update returned %+v, expected %+v", project, updateResp)
|
|
}
|
|
}
|
|
|
|
func TestProjects_Destroy(t *testing.T) {
|
|
setup()
|
|
defer teardown()
|
|
|
|
mux.HandleFunc("/v2/projects/project-1", func(w http.ResponseWriter, r *http.Request) {
|
|
testMethod(t, r, http.MethodDelete)
|
|
})
|
|
|
|
_, err := client.Projects.Delete(ctx, "project-1")
|
|
if err != nil {
|
|
t.Errorf("Projects.Delete returned error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestProjects_ListResources(t *testing.T) {
|
|
setup()
|
|
defer teardown()
|
|
|
|
expectedResources := []ProjectResource{
|
|
{
|
|
URN: "do:droplet:1",
|
|
AssignedAt: "2018-09-27 00:00:00",
|
|
Links: &ProjectResourceLinks{
|
|
Self: "http://example.com/v2/droplets/1",
|
|
},
|
|
},
|
|
{
|
|
URN: "do:floatingip:1.2.3.4",
|
|
AssignedAt: "2018-09-27 00:00:00",
|
|
Links: &ProjectResourceLinks{
|
|
Self: "http://example.com/v2/floating_ips/1.2.3.4",
|
|
},
|
|
},
|
|
}
|
|
|
|
mux.HandleFunc("/v2/projects/project-1/resources", func(w http.ResponseWriter, r *http.Request) {
|
|
testMethod(t, r, http.MethodGet)
|
|
resp, _ := json.Marshal(expectedResources)
|
|
fmt.Fprint(w, fmt.Sprintf(`{"resources":%s, "meta": {"total": 2}}`, string(resp)))
|
|
})
|
|
|
|
resources, resp, err := client.Projects.ListResources(ctx, "project-1", nil)
|
|
if err != nil {
|
|
t.Errorf("Projects.List returned error: %v", err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(resources, expectedResources) {
|
|
t.Errorf("Projects.ListResources returned resources %+v, expected %+v", resources, expectedResources)
|
|
}
|
|
|
|
expectedMeta := &Meta{Total: 2}
|
|
if !reflect.DeepEqual(resp.Meta, expectedMeta) {
|
|
t.Errorf("Projects.ListResources returned meta %+v, expected %+v", resp.Meta, expectedMeta)
|
|
}
|
|
}
|
|
|
|
func TestProjects_ListResourcesWithMultiplePages(t *testing.T) {
|
|
setup()
|
|
defer teardown()
|
|
|
|
mockResp := `
|
|
{
|
|
"resources": [
|
|
{
|
|
"urn": "do:droplet:1",
|
|
"assigned_at": "2018-09-27 00:00:00",
|
|
"links": {
|
|
"self": "http://example.com/v2/droplets/1"
|
|
}
|
|
},
|
|
{
|
|
"urn": "do:floatingip:1.2.3.4",
|
|
"assigned_at": "2018-09-27 00:00:00",
|
|
"links": {
|
|
"self": "http://example.com/v2/floating_ips/1.2.3.4"
|
|
}
|
|
}
|
|
],
|
|
"links": {
|
|
"pages": {
|
|
"next": "http://example.com/v2/projects/project-1/resources?page=2"
|
|
}
|
|
}
|
|
}`
|
|
|
|
mux.HandleFunc("/v2/projects/project-1/resources", func(w http.ResponseWriter, r *http.Request) {
|
|
testMethod(t, r, http.MethodGet)
|
|
fmt.Fprint(w, mockResp)
|
|
})
|
|
|
|
_, resp, err := client.Projects.ListResources(ctx, "project-1", nil)
|
|
if err != nil {
|
|
t.Errorf("Projects.ListResources returned error: %v", err)
|
|
}
|
|
|
|
checkCurrentPage(t, resp, 1)
|
|
}
|
|
|
|
func TestProjects_ListResourcesWithPageNumber(t *testing.T) {
|
|
setup()
|
|
defer teardown()
|
|
|
|
mockResp := `
|
|
{
|
|
"resources": [
|
|
{
|
|
"urn": "do:droplet:1",
|
|
"assigned_at": "2018-09-27 00:00:00",
|
|
"links": {
|
|
"self": "http://example.com/v2/droplets/1"
|
|
}
|
|
},
|
|
{
|
|
"urn": "do:floatingip:1.2.3.4",
|
|
"assigned_at": "2018-09-27 00:00:00",
|
|
"links": {
|
|
"self": "http://example.com/v2/floating_ips/1.2.3.4"
|
|
}
|
|
}
|
|
],
|
|
"links": {
|
|
"pages": {
|
|
"next": "http://example.com/v2/projects/project-1/resources?page=3",
|
|
"prev": "http://example.com/v2/projects/project-1/resources?page=1",
|
|
"last": "http://example.com/v2/projects/project-1/resources?page=3",
|
|
"first": "http://example.com/v2/projects/project-1/resources?page=1"
|
|
}
|
|
}
|
|
}`
|
|
|
|
mux.HandleFunc("/v2/projects/project-1/resources", func(w http.ResponseWriter, r *http.Request) {
|
|
testMethod(t, r, http.MethodGet)
|
|
fmt.Fprint(w, mockResp)
|
|
})
|
|
|
|
_, resp, err := client.Projects.ListResources(ctx, "project-1", &ListOptions{Page: 2})
|
|
if err != nil {
|
|
t.Errorf("Projects.ListResources returned error: %v", err)
|
|
}
|
|
|
|
checkCurrentPage(t, resp, 2)
|
|
}
|
|
|
|
func TestProjects_AssignFleetResourcesWithTypes(t *testing.T) {
|
|
setup()
|
|
defer teardown()
|
|
|
|
assignableResources := []interface{}{
|
|
&Droplet{ID: 1234},
|
|
&FloatingIP{IP: "1.2.3.4"},
|
|
}
|
|
|
|
mockResp := `
|
|
{
|
|
"resources": [
|
|
{
|
|
"urn": "do:droplet:1234",
|
|
"assigned_at": "2018-09-27 00:00:00",
|
|
"links": {
|
|
"self": "http://example.com/v2/droplets/1"
|
|
}
|
|
},
|
|
{
|
|
"urn": "do:floatingip:1.2.3.4",
|
|
"assigned_at": "2018-09-27 00:00:00",
|
|
"links": {
|
|
"self": "http://example.com/v2/floating_ips/1.2.3.4"
|
|
}
|
|
}
|
|
]
|
|
}`
|
|
|
|
mux.HandleFunc("/v2/projects/project-1/resources", func(w http.ResponseWriter, r *http.Request) {
|
|
testMethod(t, r, http.MethodPost)
|
|
reqBytes, respErr := ioutil.ReadAll(r.Body)
|
|
if respErr != nil {
|
|
t.Error("projects mock didn't work")
|
|
}
|
|
|
|
req := strings.TrimSuffix(string(reqBytes), "\n")
|
|
expectedReq := `{"resources":["do:droplet:1234","do:floatingip:1.2.3.4"]}`
|
|
if req != expectedReq {
|
|
t.Errorf("projects assign req didn't match up:\n expected %+v\n got %+v\n", expectedReq, req)
|
|
}
|
|
|
|
fmt.Fprint(w, mockResp)
|
|
})
|
|
|
|
_, _, err := client.Projects.AssignResources(ctx, "project-1", assignableResources...)
|
|
if err != nil {
|
|
t.Errorf("Projects.AssignResources returned error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestProjects_AssignFleetResourcesWithStrings(t *testing.T) {
|
|
setup()
|
|
defer teardown()
|
|
|
|
assignableResources := []interface{}{
|
|
"do:droplet:1234",
|
|
"do:floatingip:1.2.3.4",
|
|
}
|
|
|
|
mockResp := `
|
|
{
|
|
"resources": [
|
|
{
|
|
"urn": "do:droplet:1234",
|
|
"assigned_at": "2018-09-27 00:00:00",
|
|
"links": {
|
|
"self": "http://example.com/v2/droplets/1"
|
|
}
|
|
},
|
|
{
|
|
"urn": "do:floatingip:1.2.3.4",
|
|
"assigned_at": "2018-09-27 00:00:00",
|
|
"links": {
|
|
"self": "http://example.com/v2/floating_ips/1.2.3.4"
|
|
}
|
|
}
|
|
]
|
|
}`
|
|
|
|
mux.HandleFunc("/v2/projects/project-1/resources", func(w http.ResponseWriter, r *http.Request) {
|
|
testMethod(t, r, http.MethodPost)
|
|
reqBytes, respErr := ioutil.ReadAll(r.Body)
|
|
if respErr != nil {
|
|
t.Error("projects mock didn't work")
|
|
}
|
|
|
|
req := strings.TrimSuffix(string(reqBytes), "\n")
|
|
expectedReq := `{"resources":["do:droplet:1234","do:floatingip:1.2.3.4"]}`
|
|
if req != expectedReq {
|
|
t.Errorf("projects assign req didn't match up:\n expected %+v\n got %+v\n", expectedReq, req)
|
|
}
|
|
|
|
fmt.Fprint(w, mockResp)
|
|
})
|
|
|
|
_, _, err := client.Projects.AssignResources(ctx, "project-1", assignableResources...)
|
|
if err != nil {
|
|
t.Errorf("Projects.AssignResources returned error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestProjects_AssignFleetResourcesWithStringsAndTypes(t *testing.T) {
|
|
setup()
|
|
defer teardown()
|
|
|
|
assignableResources := []interface{}{
|
|
"do:droplet:1234",
|
|
&FloatingIP{IP: "1.2.3.4"},
|
|
}
|
|
|
|
mockResp := `
|
|
{
|
|
"resources": [
|
|
{
|
|
"urn": "do:droplet:1234",
|
|
"assigned_at": "2018-09-27 00:00:00",
|
|
"links": {
|
|
"self": "http://example.com/v2/droplets/1"
|
|
}
|
|
},
|
|
{
|
|
"urn": "do:floatingip:1.2.3.4",
|
|
"assigned_at": "2018-09-27 00:00:00",
|
|
"links": {
|
|
"self": "http://example.com/v2/floating_ips/1.2.3.4"
|
|
}
|
|
}
|
|
]
|
|
}`
|
|
|
|
mux.HandleFunc("/v2/projects/project-1/resources", func(w http.ResponseWriter, r *http.Request) {
|
|
testMethod(t, r, http.MethodPost)
|
|
reqBytes, respErr := ioutil.ReadAll(r.Body)
|
|
if respErr != nil {
|
|
t.Error("projects mock didn't work")
|
|
}
|
|
|
|
req := strings.TrimSuffix(string(reqBytes), "\n")
|
|
expectedReq := `{"resources":["do:droplet:1234","do:floatingip:1.2.3.4"]}`
|
|
if req != expectedReq {
|
|
t.Errorf("projects assign req didn't match up:\n expected %+v\n got %+v\n", expectedReq, req)
|
|
}
|
|
|
|
fmt.Fprint(w, mockResp)
|
|
})
|
|
|
|
_, _, err := client.Projects.AssignResources(ctx, "project-1", assignableResources...)
|
|
if err != nil {
|
|
t.Errorf("Projects.AssignResources returned error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestProjects_AssignFleetResourcesWithTypeWithoutURNReturnsError(t *testing.T) {
|
|
setup()
|
|
defer teardown()
|
|
|
|
type fakeType struct{}
|
|
|
|
assignableResources := []interface{}{
|
|
fakeType{},
|
|
}
|
|
|
|
_, _, err := client.Projects.AssignResources(ctx, "project-1", assignableResources...)
|
|
if err == nil {
|
|
t.Errorf("expected Projects.AssignResources to error, but it did not")
|
|
}
|
|
|
|
if err.Error() != "godo.fakeType must either be a string or have a valid URN method" {
|
|
t.Errorf("Projects.AssignResources returned the wrong error: %v", err)
|
|
}
|
|
}
|