Add support for LoadBalancers

This commit is contained in:
Viola Holownia 2017-02-14 15:36:18 -05:00
parent 0d31061e91
commit c99e714f33
4 changed files with 1073 additions and 0 deletions

1
.gitignore vendored Executable file
View File

@ -0,0 +1 @@
vendor/

View File

@ -59,6 +59,7 @@ type Client struct {
Storage StorageService
StorageActions StorageActionsService
Tags TagsService
LoadBalancers LoadBalancersService
// Optional function called after every successful request made to the DO APIs
onRequestCompleted RequestCompletionCallback
@ -167,6 +168,7 @@ func NewClient(httpClient *http.Client) *Client {
c.Storage = &StorageServiceOp{client: c}
c.StorageActions = &StorageActionsServiceOp{client: c}
c.Tags = &TagsServiceOp{client: c}
c.LoadBalancers = &LoadBalancersServiceOp{client: c}
return c
}

274
load_balancers.go Executable file
View File

@ -0,0 +1,274 @@
package godo
import (
"fmt"
)
const loadBalancersBasePath = "/v2/load_balancers"
const forwardingRulesPath = "forwarding_rules"
const dropletsPath = "droplets"
// LoadBalancersService is an interface for managing load balancers with the DigitalOcean API.
// See: https://developers.digitalocean.com/documentation/v2#load-balancers
type LoadBalancersService interface {
Get(lbID string) (*LoadBalancer, *Response, error)
List(opt *ListOptions) ([]LoadBalancer, *Response, error)
Create(lbr *LoadBalancerRequest) (*LoadBalancer, *Response, error)
Update(lbID string, lbr *LoadBalancerRequest) (*LoadBalancer, *Response, error)
Delete(lbID string) (*Response, error)
AddDroplets(lbID string, dropletIDs ...int) (*Response, error)
RemoveDroplets(lbID string, dropletIDs ...int) (*Response, error)
AddForwardingRules(lbID string, rules ...ForwardingRule) (*Response, error)
RemoveForwardingRules(lbID string, rules ...ForwardingRule) (*Response, error)
}
// LoadBalancer represents a DigitalOcean load balancer configuration.
type LoadBalancer struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
IP string `json:"ip,omitempty"`
Algorithm string `json:"algorithm,omitempty"`
Status string `json:"status,omitempty"`
Created string `json:"created_at,omitempty"`
ForwardingRules []ForwardingRule `json:"forwarding_rules,omitempty"`
HealthCheck *HealthCheck `json:"health_check,omitempty"`
StickySessions *StickySessions `json:"sticky_sessions,omitempty"`
Region *Region `json:"region,omitempty"`
DropletIDs []int `json:"droplet_ids,omitempty"`
Tag string `json:"tag,omitempty"`
RedirectHttpToHttps bool `json:"redirect_http_to_https,omitempty"`
}
// String creates a human-readable description of a LoadBalancer.
func (l LoadBalancer) String() string {
return Stringify(l)
}
// ForwardingRule represents load balancer forwarding rules.
type ForwardingRule struct {
EntryProtocol string `json:"entry_protocol,omitempty"`
EntryPort int `json:"entry_port,omitempty"`
TargetProtocol string `json:"target_protocol,omitempty"`
TargetPort int `json:"target_port,omitempty"`
CertificateID string `json:"certificate_id,omitempty"`
TlsPassthrough bool `json:"tls_passthrough,omitempty"`
}
// String creates a human-readable description of a ForwardingRule.
func (f ForwardingRule) String() string {
return Stringify(f)
}
// HealthCheck represents optional load balancer health check rules.
type HealthCheck struct {
Protocol string `json:"protocol,omitempty"`
Port int `json:"port,omitempty"`
Path string `json:"path,omitempty"`
CheckIntervalSeconds int `json:"check_interval_seconds,omitempty"`
ResponseTimeoutSeconds int `json:"response_timeout_seconds,omitempty"`
HealthyThreshold int `json:"healthy_threshold,omitempty"`
UnhealthyThreshold int `json:"unhealthy_threshold,omitempty"`
}
// String creates a human-readable description of a HealthCheck.
func (h HealthCheck) String() string {
return Stringify(h)
}
// StickySessions represents optional load balancer session affinity rules.
type StickySessions struct {
Type string `json:"type,omitempty"`
CookieName string `json:"cookie_name,omitempty"`
CookieTtlSeconds int `json:"cookie_ttl_seconds,omitempty"`
}
// String creates a human-readable description of a StickySessions instance.
func (s StickySessions) String() string {
return Stringify(s)
}
// LoadBalancerRequest represents the configuration to be applied to an existing or a new load balancer.
type LoadBalancerRequest struct {
Name string `json:"name,omitempty"`
Algorithm string `json:"algorithm,omitempty"`
Region string `json:"region,omitempty"`
ForwardingRules []ForwardingRule `json:"forwarding_rules,omitempty"`
HealthCheck *HealthCheck `json:"health_check,omitempty"`
StickySessions *StickySessions `json:"sticky_sessions,omitempty"`
DropletIDs []int `json:"droplet_ids,omitempty"`
Tag string `json:"tag,omitempty"`
RedirectHttpToHttps bool `json:"redirect_http_to_https,omitempty"`
}
// String creates a human-readable description of a LoadBalancerRequest.
func (l LoadBalancerRequest) String() string {
return Stringify(l)
}
type forwardingRulesRequest struct {
Rules []ForwardingRule `json:"forwarding_rules,omitempty"`
}
func (l forwardingRulesRequest) String() string {
return Stringify(l)
}
type dropletIDsRequest struct {
IDs []int `json:"droplet_ids,omitempty"`
}
func (l dropletIDsRequest) String() string {
return Stringify(l)
}
type loadBalancersRoot struct {
LoadBalancers []LoadBalancer `json:"load_balancers"`
Links *Links `json:"links"`
}
type loadBalancerRoot struct {
LoadBalancer *LoadBalancer `json:"load_balancer"`
}
// LoadBalancersServiceOp handles communication with load balancer-related methods of the DigitalOcean API.
type LoadBalancersServiceOp struct {
client *Client
}
var _ LoadBalancersService = &LoadBalancersServiceOp{}
// Get an existing load balancer by its identifier.
func (l *LoadBalancersServiceOp) Get(lbID string) (*LoadBalancer, *Response, error) {
path := fmt.Sprintf("%s/%s", loadBalancersBasePath, lbID)
req, err := l.client.NewRequest("GET", path, nil)
if err != nil {
return nil, nil, err
}
root := new(loadBalancerRoot)
resp, err := l.client.Do(req, root)
if err != nil {
return nil, resp, err
}
return root.LoadBalancer, resp, err
}
// List load balancers, with optional pagination.
func (l *LoadBalancersServiceOp) List(opt *ListOptions) ([]LoadBalancer, *Response, error) {
path, err := addOptions(loadBalancersBasePath, opt)
if err != nil {
return nil, nil, err
}
req, err := l.client.NewRequest("GET", path, nil)
if err != nil {
return nil, nil, err
}
root := new(loadBalancersRoot)
resp, err := l.client.Do(req, root)
if err != nil {
return nil, resp, err
}
if l := root.Links; l != nil {
resp.Links = l
}
return root.LoadBalancers, resp, err
}
// Create a new load balancer with a given configuration.
func (l *LoadBalancersServiceOp) Create(lbr *LoadBalancerRequest) (*LoadBalancer, *Response, error) {
req, err := l.client.NewRequest("POST", loadBalancersBasePath, lbr)
if err != nil {
return nil, nil, err
}
root := new(loadBalancerRoot)
resp, err := l.client.Do(req, root)
if err != nil {
return nil, resp, err
}
return root.LoadBalancer, resp, err
}
// Update an existing load balancer with new configuration.
func (l *LoadBalancersServiceOp) Update(lbID string, lbr *LoadBalancerRequest) (*LoadBalancer, *Response, error) {
path := fmt.Sprintf("%s/%s", loadBalancersBasePath, lbID)
req, err := l.client.NewRequest("PUT", path, lbr)
if err != nil {
return nil, nil, err
}
root := new(loadBalancerRoot)
resp, err := l.client.Do(req, root)
if err != nil {
return nil, resp, err
}
return root.LoadBalancer, resp, err
}
// Delete a load balancer by its identifier.
func (l *LoadBalancersServiceOp) Delete(ldID string) (*Response, error) {
path := fmt.Sprintf("%s/%s", loadBalancersBasePath, ldID)
req, err := l.client.NewRequest("DELETE", path, nil)
if err != nil {
return nil, err
}
return l.client.Do(req, nil)
}
// AddDroplets adds droplets to a load balancer.
func (l *LoadBalancersServiceOp) AddDroplets(lbID string, dropletIDs ...int) (*Response, error) {
path := fmt.Sprintf("%s/%s/%s", loadBalancersBasePath, lbID, dropletsPath)
req, err := l.client.NewRequest("POST", path, &dropletIDsRequest{IDs: dropletIDs})
if err != nil {
return nil, err
}
return l.client.Do(req, nil)
}
// RemoveDroplets removes droplets from a load balancer.
func (l *LoadBalancersServiceOp) RemoveDroplets(lbID string, dropletIDs ...int) (*Response, error) {
path := fmt.Sprintf("%s/%s/%s", loadBalancersBasePath, lbID, dropletsPath)
req, err := l.client.NewRequest("DELETE", path, &dropletIDsRequest{IDs: dropletIDs})
if err != nil {
return nil, err
}
return l.client.Do(req, nil)
}
// AddForwardingRules adds forwarding rules to a load balancer.
func (l *LoadBalancersServiceOp) AddForwardingRules(lbID string, rules ...ForwardingRule) (*Response, error) {
path := fmt.Sprintf("%s/%s/%s", loadBalancersBasePath, lbID, forwardingRulesPath)
req, err := l.client.NewRequest("POST", path, &forwardingRulesRequest{Rules: rules})
if err != nil {
return nil, err
}
return l.client.Do(req, nil)
}
// RemoveForwardingRules removes forwarding rules from a load balancer.
func (l *LoadBalancersServiceOp) RemoveForwardingRules(lbID string, rules ...ForwardingRule) (*Response, error) {
path := fmt.Sprintf("%s/%s/%s", loadBalancersBasePath, lbID, forwardingRulesPath)
req, err := l.client.NewRequest("DELETE", path, &forwardingRulesRequest{Rules: rules})
if err != nil {
return nil, err
}
return l.client.Do(req, nil)
}

796
load_balancers_test.go Executable file
View File

@ -0,0 +1,796 @@
package godo
import (
"encoding/json"
"fmt"
"net/http"
"testing"
"github.com/stretchr/testify/assert"
)
var lbListJSONResponse = `
{
"load_balancers":[
{
"id":"37e6be88-01ec-4ec7-9bc6-a514d4719057",
"name":"example-lb-01",
"ip":"46.214.185.203",
"algorithm":"round_robin",
"status":"active",
"created_at":"2016-12-15T14:16:36Z",
"forwarding_rules":[
{
"entry_protocol":"https",
"entry_port":443,
"target_protocol":"http",
"target_port":80,
"certificate_id":"a-b-c"
}
],
"health_check":{
"protocol":"http",
"port":80,
"path":"/index.html",
"check_interval_seconds":10,
"response_timeout_seconds":5,
"healthy_threshold":5,
"unhealthy_threshold":3
},
"sticky_sessions":{
"type":"cookies",
"cookie_name":"DO-LB",
"cookie_ttl_seconds":5
},
"region":{
"name":"New York 1",
"slug":"nyc1",
"sizes":[
"512mb",
"1gb",
"2gb",
"4gb",
"8gb",
"16gb"
],
"features":[
"private_networking",
"backups",
"ipv6",
"metadata",
"storage"
],
"available":true
},
"droplet_ids":[
2,
21
]
}
],
"links":{
"pages":{
"last":"http://localhost:3001/v2/load_balancers?page=3&per_page=1",
"next":"http://localhost:3001/v2/load_balancers?page=2&per_page=1"
}
},
"meta":{
"total":3
}
}
`
var lbCreateJSONResponse = `
{
"load_balancer":{
"id":"8268a81c-fcf5-423e-a337-bbfe95817f23",
"name":"example-lb-01",
"ip":"",
"algorithm":"round_robin",
"status":"new",
"created_at":"2016-12-15T14:19:09Z",
"forwarding_rules":[
{
"entry_protocol":"https",
"entry_port":443,
"target_protocol":"http",
"target_port":80,
"certificate_id":"a-b-c"
},
{
"entry_protocol":"https",
"entry_port":444,
"target_protocol":"https",
"target_port":443,
"tls_passthrough":true
}
],
"health_check":{
"protocol":"http",
"port":80,
"path":"/index.html",
"check_interval_seconds":10,
"response_timeout_seconds":5,
"healthy_threshold":5,
"unhealthy_threshold":3
},
"sticky_sessions":{
"type":"cookies",
"cookie_name":"DO-LB",
"cookie_ttl_seconds":5
},
"region":{
"name":"New York 1",
"slug":"nyc1",
"sizes":[
"512mb",
"1gb",
"2gb",
"4gb",
"8gb",
"16gb"
],
"features":[
"private_networking",
"backups",
"ipv6",
"metadata",
"storage"
],
"available":true
},
"droplet_ids":[
2,
21
],
"redirect_http_to_https":true
}
}
`
var lbGetJSONResponse = `
{
"load_balancer":{
"id":"37e6be88-01ec-4ec7-9bc6-a514d4719057",
"name":"example-lb-01",
"ip":"46.214.185.203",
"algorithm":"round_robin",
"status":"active",
"created_at":"2016-12-15T14:16:36Z",
"forwarding_rules":[
{
"entry_protocol":"https",
"entry_port":443,
"target_protocol":"http",
"target_port":80,
"certificate_id":"a-b-c"
}
],
"health_check":{
"protocol":"http",
"port":80,
"path":"/index.html",
"check_interval_seconds":10,
"response_timeout_seconds":5,
"healthy_threshold":5,
"unhealthy_threshold":3
},
"sticky_sessions":{
"type":"cookies",
"cookie_name":"DO-LB",
"cookie_ttl_seconds":5
},
"region":{
"name":"New York 1",
"slug":"nyc1",
"sizes":[
"512mb",
"1gb",
"2gb",
"4gb",
"8gb",
"16gb"
],
"features":[
"private_networking",
"backups",
"ipv6",
"metadata",
"storage"
],
"available":true
},
"droplet_ids":[
2,
21
]
}
}
`
var lbUpdateJSONResponse = `
{
"load_balancer":{
"id":"8268a81c-fcf5-423e-a337-bbfe95817f23",
"name":"example-lb-01",
"ip":"12.34.56.78",
"algorithm":"least_connections",
"status":"active",
"created_at":"2016-12-15T14:19:09Z",
"forwarding_rules":[
{
"entry_protocol":"http",
"entry_port":80,
"target_protocol":"http",
"target_port":80
},
{
"entry_protocol":"https",
"entry_port":443,
"target_protocol":"http",
"target_port":80,
"certificate_id":"a-b-c"
}
],
"health_check":{
"protocol":"tcp",
"port":80,
"path":"",
"check_interval_seconds":10,
"response_timeout_seconds":5,
"healthy_threshold":5,
"unhealthy_threshold":3
},
"sticky_sessions":{
"type":"none"
},
"region":{
"name":"New York 1",
"slug":"nyc1",
"sizes":[
"512mb",
"1gb",
"2gb",
"4gb",
"8gb",
"16gb"
],
"features":[
"private_networking",
"backups",
"ipv6",
"metadata",
"storage"
],
"available":true
},
"droplet_ids":[
2,
21
]
}
}
`
func TestLoadBlanacers_Get(t *testing.T) {
setup()
defer teardown()
path := "/v2/load_balancers"
loadBalancerId := "37e6be88-01ec-4ec7-9bc6-a514d4719057"
path = fmt.Sprintf("%s/%s", path, loadBalancerId)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, lbGetJSONResponse)
})
loadBalancer, _, err := client.LoadBalancers.Get(loadBalancerId)
if err != nil {
t.Errorf("LoadBalancers.Get returned error: %v", err)
}
expected := &LoadBalancer{
ID: "37e6be88-01ec-4ec7-9bc6-a514d4719057",
Name: "example-lb-01",
IP: "46.214.185.203",
Algorithm: "round_robin",
Status: "active",
Created: "2016-12-15T14:16:36Z",
ForwardingRules: []ForwardingRule{
{
EntryProtocol: "https",
EntryPort: 443,
TargetProtocol: "http",
TargetPort: 80,
CertificateID: "a-b-c",
TlsPassthrough: false,
},
},
HealthCheck: &HealthCheck{
Protocol: "http",
Port: 80,
Path: "/index.html",
CheckIntervalSeconds: 10,
ResponseTimeoutSeconds: 5,
HealthyThreshold: 5,
UnhealthyThreshold: 3,
},
StickySessions: &StickySessions{
Type: "cookies",
CookieName: "DO-LB",
CookieTtlSeconds: 5,
},
Region: &Region{
Slug: "nyc1",
Name: "New York 1",
Sizes: []string{"512mb", "1gb", "2gb", "4gb", "8gb", "16gb"},
Available: true,
Features: []string{"private_networking", "backups", "ipv6", "metadata", "storage"},
},
DropletIDs: []int{2, 21},
}
assert.Equal(t, expected, loadBalancer)
}
func TestLoadBlanacers_Create(t *testing.T) {
setup()
defer teardown()
createRequest := &LoadBalancerRequest{
Name: "example-lb-01",
Algorithm: "round_robin",
Region: "nyc1",
ForwardingRules: []ForwardingRule{
{
EntryProtocol: "https",
EntryPort: 443,
TargetProtocol: "http",
TargetPort: 80,
CertificateID: "a-b-c",
},
},
HealthCheck: &HealthCheck{
Protocol: "http",
Port: 80,
Path: "/index.html",
CheckIntervalSeconds: 10,
ResponseTimeoutSeconds: 5,
UnhealthyThreshold: 3,
HealthyThreshold: 5,
},
StickySessions: &StickySessions{
Type: "cookies",
CookieName: "DO-LB",
CookieTtlSeconds: 5,
},
Tag: "my-tag",
DropletIDs: []int{2, 21},
RedirectHttpToHttps: true,
}
path := "/v2/load_balancers"
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
v := new(LoadBalancerRequest)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatal(err)
}
testMethod(t, r, "POST")
assert.Equal(t, createRequest, v)
fmt.Fprint(w, lbCreateJSONResponse)
})
loadBalancer, _, err := client.LoadBalancers.Create(createRequest)
if err != nil {
t.Errorf("LoadBalancers.Create returned error: %v", err)
}
expected := &LoadBalancer{
ID: "8268a81c-fcf5-423e-a337-bbfe95817f23",
Name: "example-lb-01",
Algorithm: "round_robin",
Status: "new",
Created: "2016-12-15T14:19:09Z",
ForwardingRules: []ForwardingRule{
{
EntryProtocol: "https",
EntryPort: 443,
TargetProtocol: "http",
TargetPort: 80,
CertificateID: "a-b-c",
TlsPassthrough: false,
},
{
EntryProtocol: "https",
EntryPort: 444,
TargetProtocol: "https",
TargetPort: 443,
CertificateID: "",
TlsPassthrough: true,
},
},
HealthCheck: &HealthCheck{
Protocol: "http",
Port: 80,
Path: "/index.html",
CheckIntervalSeconds: 10,
ResponseTimeoutSeconds: 5,
HealthyThreshold: 5,
UnhealthyThreshold: 3,
},
StickySessions: &StickySessions{
Type: "cookies",
CookieName: "DO-LB",
CookieTtlSeconds: 5,
},
Region: &Region{
Slug: "nyc1",
Name: "New York 1",
Sizes: []string{"512mb", "1gb", "2gb", "4gb", "8gb", "16gb"},
Available: true,
Features: []string{"private_networking", "backups", "ipv6", "metadata", "storage"},
},
DropletIDs: []int{2, 21},
RedirectHttpToHttps: true,
}
assert.Equal(t, expected, loadBalancer)
}
func TestLoadBlanacers_Update(t *testing.T) {
setup()
defer teardown()
updateRequest := &LoadBalancerRequest{
Name: "example-lb-01",
Algorithm: "least_connections",
Region: "nyc1",
ForwardingRules: []ForwardingRule{
{
EntryProtocol: "http",
EntryPort: 80,
TargetProtocol: "http",
TargetPort: 80,
},
{
EntryProtocol: "https",
EntryPort: 443,
TargetProtocol: "http",
TargetPort: 80,
CertificateID: "a-b-c",
},
},
HealthCheck: &HealthCheck{
Protocol: "tcp",
Port: 80,
Path: "",
CheckIntervalSeconds: 10,
ResponseTimeoutSeconds: 5,
UnhealthyThreshold: 3,
HealthyThreshold: 5,
},
StickySessions: &StickySessions{
Type: "none",
},
DropletIDs: []int{2, 21},
}
path := "/v2/load_balancers"
loadBalancerId := "8268a81c-fcf5-423e-a337-bbfe95817f23"
path = fmt.Sprintf("%s/%s", path, loadBalancerId)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
v := new(LoadBalancerRequest)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatal(err)
}
testMethod(t, r, "PUT")
assert.Equal(t, updateRequest, v)
fmt.Fprint(w, lbUpdateJSONResponse)
})
loadBalancer, _, err := client.LoadBalancers.Update(loadBalancerId, updateRequest)
if err != nil {
t.Errorf("LoadBalancers.Update returned error: %v", err)
}
expected := &LoadBalancer{
ID: "8268a81c-fcf5-423e-a337-bbfe95817f23",
Name: "example-lb-01",
IP: "12.34.56.78",
Algorithm: "least_connections",
Status: "active",
Created: "2016-12-15T14:19:09Z",
ForwardingRules: []ForwardingRule{
{
EntryProtocol: "http",
EntryPort: 80,
TargetProtocol: "http",
TargetPort: 80,
},
{
EntryProtocol: "https",
EntryPort: 443,
TargetProtocol: "http",
TargetPort: 80,
CertificateID: "a-b-c",
},
},
HealthCheck: &HealthCheck{
Protocol: "tcp",
Port: 80,
Path: "",
CheckIntervalSeconds: 10,
ResponseTimeoutSeconds: 5,
UnhealthyThreshold: 3,
HealthyThreshold: 5,
},
StickySessions: &StickySessions{
Type: "none",
},
Region: &Region{
Slug: "nyc1",
Name: "New York 1",
Sizes: []string{"512mb", "1gb", "2gb", "4gb", "8gb", "16gb"},
Available: true,
Features: []string{"private_networking", "backups", "ipv6", "metadata", "storage"},
},
DropletIDs: []int{2, 21},
}
assert.Equal(t, expected, loadBalancer)
}
func TestLoadBlanacers_List(t *testing.T) {
setup()
defer teardown()
path := "/v2/load_balancers"
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, lbListJSONResponse)
})
loadBalancers, _, err := client.LoadBalancers.List(nil)
if err != nil {
t.Errorf("LoadBalancers.List returned error: %v", err)
}
expected := []LoadBalancer{
{
ID: "37e6be88-01ec-4ec7-9bc6-a514d4719057",
Name: "example-lb-01",
IP: "46.214.185.203",
Algorithm: "round_robin",
Status: "active",
Created: "2016-12-15T14:16:36Z",
ForwardingRules: []ForwardingRule{
{
EntryProtocol: "https",
EntryPort: 443,
TargetProtocol: "http",
TargetPort: 80,
CertificateID: "a-b-c",
},
},
HealthCheck: &HealthCheck{
Protocol: "http",
Port: 80,
Path: "/index.html",
CheckIntervalSeconds: 10,
ResponseTimeoutSeconds: 5,
HealthyThreshold: 5,
UnhealthyThreshold: 3,
},
StickySessions: &StickySessions{
Type: "cookies",
CookieName: "DO-LB",
CookieTtlSeconds: 5,
},
Region: &Region{
Slug: "nyc1",
Name: "New York 1",
Sizes: []string{"512mb", "1gb", "2gb", "4gb", "8gb", "16gb"},
Available: true,
Features: []string{"private_networking", "backups", "ipv6", "metadata", "storage"},
},
DropletIDs: []int{2, 21},
},
}
assert.Equal(t, expected, loadBalancers)
}
func TestLoadBlanacers_List_Pagination(t *testing.T) {
setup()
defer teardown()
path := "/v2/load_balancers"
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
testFormValues(t, r, map[string]string{"page": "2"})
fmt.Fprint(w, lbListJSONResponse)
})
opts := &ListOptions{Page: 2}
_, resp, err := client.LoadBalancers.List(opts)
if err != nil {
t.Errorf("LoadBalancers.List returned error: %v", err)
}
assert.Equal(t, "http://localhost:3001/v2/load_balancers?page=2&per_page=1", resp.Links.Pages.Next)
assert.Equal(t, "http://localhost:3001/v2/load_balancers?page=3&per_page=1", resp.Links.Pages.Last)
}
func TestLoadBlanacers_Delete(t *testing.T) {
setup()
defer teardown()
lbID := "37e6be88-01ec-4ec7-9bc6-a514d4719057"
path := "/v2/load_balancers"
path = fmt.Sprintf("%s/%s", path, lbID)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE")
})
_, err := client.LoadBalancers.Delete(lbID)
if err != nil {
t.Errorf("LoadBalancers.Delete returned error: %v", err)
}
}
func TestLoadBlanacers_AddDroplets(t *testing.T) {
setup()
defer teardown()
dropletIdsRequest := &dropletIDsRequest{
IDs: []int{42, 44},
}
lbID := "37e6be88-01ec-4ec7-9bc6-a514d4719057"
path := fmt.Sprintf("/v2/load_balancers/%s/droplets", lbID)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
v := new(dropletIDsRequest)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatal(err)
}
testMethod(t, r, "POST")
assert.Equal(t, dropletIdsRequest, v)
fmt.Fprint(w, nil)
})
_, err := client.LoadBalancers.AddDroplets(lbID, dropletIdsRequest.IDs...)
if err != nil {
t.Errorf("LoadBalancers.AddDroplets returned error: %v", err)
}
}
func TestLoadBlanacers_RemoveDroplets(t *testing.T) {
setup()
defer teardown()
dropletIdsRequest := &dropletIDsRequest{
IDs: []int{2, 21},
}
lbID := "37e6be88-01ec-4ec7-9bc6-a514d4719057"
path := fmt.Sprintf("/v2/load_balancers/%s/droplets", lbID)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
v := new(dropletIDsRequest)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatal(err)
}
testMethod(t, r, "DELETE")
assert.Equal(t, dropletIdsRequest, v)
fmt.Fprint(w, nil)
})
_, err := client.LoadBalancers.RemoveDroplets(lbID, dropletIdsRequest.IDs...)
if err != nil {
t.Errorf("LoadBalancers.RemoveDroplets returned error: %v", err)
}
}
func TestLoadBlanacers_AddForwardingRules(t *testing.T) {
setup()
defer teardown()
frr := &forwardingRulesRequest{
Rules: []ForwardingRule{
{
EntryProtocol: "https",
EntryPort: 444,
TargetProtocol: "http",
TargetPort: 81,
CertificateID: "b2abc00f-d3c4-426c-9f0b-b2f7a3ff7527",
},
{
EntryProtocol: "tcp",
EntryPort: 8080,
TargetProtocol: "tcp",
TargetPort: 8081,
},
},
}
lbID := "37e6be88-01ec-4ec7-9bc6-a514d4719057"
path := fmt.Sprintf("/v2/load_balancers/%s/forwarding_rules", lbID)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
v := new(forwardingRulesRequest)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatal(err)
}
testMethod(t, r, "POST")
assert.Equal(t, frr, v)
fmt.Fprint(w, nil)
})
_, err := client.LoadBalancers.AddForwardingRules(lbID, frr.Rules...)
if err != nil {
t.Errorf("LoadBalancers.AddForwardingRules returned error: %v", err)
}
}
func TestLoadBlanacers_RemoveForwardingRules(t *testing.T) {
setup()
defer teardown()
frr := &forwardingRulesRequest{
Rules: []ForwardingRule{
{
EntryProtocol: "https",
EntryPort: 444,
TargetProtocol: "http",
TargetPort: 81,
},
{
EntryProtocol: "tcp",
EntryPort: 8080,
TargetProtocol: "tcp",
TargetPort: 8081,
},
},
}
lbID := "37e6be88-01ec-4ec7-9bc6-a514d4719057"
path := fmt.Sprintf("/v2/load_balancers/%s/forwarding_rules", lbID)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
v := new(forwardingRulesRequest)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatal(err)
}
testMethod(t, r, "DELETE")
assert.Equal(t, frr, v)
fmt.Fprint(w, nil)
})
_, err := client.LoadBalancers.RemoveForwardingRules(lbID, frr.Rules...)
if err != nil {
t.Errorf("LoadBalancers.RemoveForwardingRules returned error: %v", err)
}
}