Add support for LoadBalancers
This commit is contained in:
parent
0d31061e91
commit
c99e714f33
|
@ -0,0 +1 @@
|
|||
vendor/
|
2
godo.go
2
godo.go
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue