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(ctx, 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(ctx, 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(ctx, 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(ctx, 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(ctx, 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(ctx, 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(ctx, 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(ctx, 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(ctx, 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(ctx, lbID, frr.Rules...) if err != nil { t.Errorf("LoadBalancers.RemoveForwardingRules returned error: %v", err) } }