1package godo
2
3import (
4	"encoding/json"
5	"fmt"
6	"net/http"
7	"testing"
8
9	"github.com/stretchr/testify/assert"
10)
11
12var lbListJSONResponse = `
13{
14	"load_balancers":[
15        {
16            "id":"37e6be88-01ec-4ec7-9bc6-a514d4719057",
17            "name":"example-lb-01",
18            "ip":"46.214.185.203",
19            "algorithm":"round_robin",
20            "status":"active",
21            "created_at":"2016-12-15T14:16:36Z",
22            "forwarding_rules":[
23                {
24                    "entry_protocol":"https",
25                    "entry_port":443,
26                    "target_protocol":"http",
27                    "target_port":80,
28                    "certificate_id":"a-b-c"
29                }
30            ],
31            "health_check":{
32                "protocol":"http",
33                "port":80,
34                "path":"/index.html",
35                "check_interval_seconds":10,
36                "response_timeout_seconds":5,
37                "healthy_threshold":5,
38                "unhealthy_threshold":3
39            },
40            "sticky_sessions":{
41                "type":"cookies",
42                "cookie_name":"DO-LB",
43                "cookie_ttl_seconds":5
44            },
45            "region":{
46            	"name":"New York 1",
47                "slug":"nyc1",
48                "sizes":[
49                    "512mb",
50                    "1gb",
51                    "2gb",
52                    "4gb",
53                    "8gb",
54                    "16gb"
55                ],
56                "features":[
57                    "private_networking",
58                    "backups",
59                    "ipv6",
60                    "metadata",
61                    "storage"
62                ],
63                "available":true
64            },
65            "droplet_ids":[
66                2,
67                21
68            ]
69        }
70    ],
71    "links":{
72        "pages":{
73            "last":"http://localhost:3001/v2/load_balancers?page=3&per_page=1",
74            "next":"http://localhost:3001/v2/load_balancers?page=2&per_page=1"
75        }
76    },
77    "meta":{
78        "total":3
79    }
80}
81`
82
83var lbCreateJSONResponse = `
84{
85    "load_balancer":{
86        "id":"8268a81c-fcf5-423e-a337-bbfe95817f23",
87        "name":"example-lb-01",
88        "ip":"",
89        "algorithm":"round_robin",
90        "status":"new",
91        "created_at":"2016-12-15T14:19:09Z",
92        "forwarding_rules":[
93            {
94                "entry_protocol":"https",
95                "entry_port":443,
96                "target_protocol":"http",
97                "target_port":80,
98                "certificate_id":"a-b-c"
99            },
100            {
101                "entry_protocol":"https",
102                "entry_port":444,
103                "target_protocol":"https",
104                "target_port":443,
105                "tls_passthrough":true
106            }
107        ],
108        "health_check":{
109            "protocol":"http",
110            "port":80,
111            "path":"/index.html",
112            "check_interval_seconds":10,
113            "response_timeout_seconds":5,
114            "healthy_threshold":5,
115            "unhealthy_threshold":3
116        },
117        "sticky_sessions":{
118            "type":"cookies",
119            "cookie_name":"DO-LB",
120            "cookie_ttl_seconds":5
121        },
122        "region":{
123            "name":"New York 1",
124            "slug":"nyc1",
125            "sizes":[
126                "512mb",
127                "1gb",
128                "2gb",
129                "4gb",
130                "8gb",
131                "16gb"
132            ],
133            "features":[
134                "private_networking",
135                "backups",
136                "ipv6",
137                "metadata",
138                "storage"
139            ],
140            "available":true
141		},
142		"tags": ["my-tag"],
143        "droplet_ids":[
144            2,
145            21
146        ],
147        "redirect_http_to_https":true
148    }
149}
150`
151
152var lbGetJSONResponse = `
153{
154    "load_balancer":{
155        "id":"37e6be88-01ec-4ec7-9bc6-a514d4719057",
156        "name":"example-lb-01",
157        "ip":"46.214.185.203",
158        "algorithm":"round_robin",
159        "status":"active",
160        "created_at":"2016-12-15T14:16:36Z",
161        "forwarding_rules":[
162            {
163                "entry_protocol":"https",
164                "entry_port":443,
165                "target_protocol":"http",
166                "target_port":80,
167                "certificate_id":"a-b-c"
168            }
169        ],
170        "health_check":{
171            "protocol":"http",
172            "port":80,
173            "path":"/index.html",
174            "check_interval_seconds":10,
175            "response_timeout_seconds":5,
176            "healthy_threshold":5,
177            "unhealthy_threshold":3
178        },
179        "sticky_sessions":{
180            "type":"cookies",
181            "cookie_name":"DO-LB",
182            "cookie_ttl_seconds":5
183        },
184        "region":{
185            "name":"New York 1",
186            "slug":"nyc1",
187            "sizes":[
188                "512mb",
189                "1gb",
190                "2gb",
191                "4gb",
192                "8gb",
193                "16gb"
194            ],
195            "features":[
196                "private_networking",
197                "backups",
198                "ipv6",
199                "metadata",
200                "storage"
201            ],
202            "available":true
203        },
204        "droplet_ids":[
205            2,
206            21
207        ]
208    }
209}
210`
211
212var lbUpdateJSONResponse = `
213{
214    "load_balancer":{
215        "id":"8268a81c-fcf5-423e-a337-bbfe95817f23",
216        "name":"example-lb-01",
217        "ip":"12.34.56.78",
218        "algorithm":"least_connections",
219        "status":"active",
220        "created_at":"2016-12-15T14:19:09Z",
221        "forwarding_rules":[
222            {
223                "entry_protocol":"http",
224                "entry_port":80,
225                "target_protocol":"http",
226                "target_port":80
227            },
228            {
229                "entry_protocol":"https",
230                "entry_port":443,
231                "target_protocol":"http",
232                "target_port":80,
233                "certificate_id":"a-b-c"
234            }
235        ],
236        "health_check":{
237            "protocol":"tcp",
238            "port":80,
239            "path":"",
240            "check_interval_seconds":10,
241            "response_timeout_seconds":5,
242            "healthy_threshold":5,
243            "unhealthy_threshold":3
244        },
245        "sticky_sessions":{
246            "type":"none"
247        },
248        "region":{
249            "name":"New York 1",
250            "slug":"nyc1",
251            "sizes":[
252                "512mb",
253                "1gb",
254                "2gb",
255                "4gb",
256                "8gb",
257                "16gb"
258            ],
259            "features":[
260                "private_networking",
261                "backups",
262                "ipv6",
263                "metadata",
264                "storage"
265            ],
266            "available":true
267        },
268        "droplet_ids":[
269            2,
270            21
271        ]
272    }
273}
274`
275
276func TestLoadBalancers_Get(t *testing.T) {
277	setup()
278	defer teardown()
279
280	path := "/v2/load_balancers"
281	loadBalancerId := "37e6be88-01ec-4ec7-9bc6-a514d4719057"
282	path = fmt.Sprintf("%s/%s", path, loadBalancerId)
283	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
284		testMethod(t, r, http.MethodGet)
285		fmt.Fprint(w, lbGetJSONResponse)
286	})
287
288	loadBalancer, _, err := client.LoadBalancers.Get(ctx, loadBalancerId)
289	if err != nil {
290		t.Errorf("LoadBalancers.Get returned error: %v", err)
291	}
292
293	expected := &LoadBalancer{
294		ID:        "37e6be88-01ec-4ec7-9bc6-a514d4719057",
295		Name:      "example-lb-01",
296		IP:        "46.214.185.203",
297		Algorithm: "round_robin",
298		Status:    "active",
299		Created:   "2016-12-15T14:16:36Z",
300		ForwardingRules: []ForwardingRule{
301			{
302				EntryProtocol:  "https",
303				EntryPort:      443,
304				TargetProtocol: "http",
305				TargetPort:     80,
306				CertificateID:  "a-b-c",
307				TlsPassthrough: false,
308			},
309		},
310		HealthCheck: &HealthCheck{
311			Protocol:               "http",
312			Port:                   80,
313			Path:                   "/index.html",
314			CheckIntervalSeconds:   10,
315			ResponseTimeoutSeconds: 5,
316			HealthyThreshold:       5,
317			UnhealthyThreshold:     3,
318		},
319		StickySessions: &StickySessions{
320			Type:             "cookies",
321			CookieName:       "DO-LB",
322			CookieTtlSeconds: 5,
323		},
324		Region: &Region{
325			Slug:      "nyc1",
326			Name:      "New York 1",
327			Sizes:     []string{"512mb", "1gb", "2gb", "4gb", "8gb", "16gb"},
328			Available: true,
329			Features:  []string{"private_networking", "backups", "ipv6", "metadata", "storage"},
330		},
331		DropletIDs: []int{2, 21},
332	}
333
334	assert.Equal(t, expected, loadBalancer)
335}
336
337func TestLoadBalancers_Create(t *testing.T) {
338	setup()
339	defer teardown()
340
341	createRequest := &LoadBalancerRequest{
342		Name:      "example-lb-01",
343		Algorithm: "round_robin",
344		Region:    "nyc1",
345		ForwardingRules: []ForwardingRule{
346			{
347				EntryProtocol:  "https",
348				EntryPort:      443,
349				TargetProtocol: "http",
350				TargetPort:     80,
351				CertificateID:  "a-b-c",
352			},
353		},
354		HealthCheck: &HealthCheck{
355			Protocol:               "http",
356			Port:                   80,
357			Path:                   "/index.html",
358			CheckIntervalSeconds:   10,
359			ResponseTimeoutSeconds: 5,
360			UnhealthyThreshold:     3,
361			HealthyThreshold:       5,
362		},
363		StickySessions: &StickySessions{
364			Type:             "cookies",
365			CookieName:       "DO-LB",
366			CookieTtlSeconds: 5,
367		},
368		Tag:                 "my-tag",
369		Tags:                []string{"my-tag"},
370		DropletIDs:          []int{2, 21},
371		RedirectHttpToHttps: true,
372	}
373
374	path := "/v2/load_balancers"
375	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
376		v := new(LoadBalancerRequest)
377		err := json.NewDecoder(r.Body).Decode(v)
378		if err != nil {
379			t.Fatal(err)
380		}
381
382		testMethod(t, r, http.MethodPost)
383		assert.Equal(t, createRequest, v)
384
385		fmt.Fprint(w, lbCreateJSONResponse)
386	})
387
388	loadBalancer, _, err := client.LoadBalancers.Create(ctx, createRequest)
389	if err != nil {
390		t.Errorf("LoadBalancers.Create returned error: %v", err)
391	}
392
393	expected := &LoadBalancer{
394		ID:        "8268a81c-fcf5-423e-a337-bbfe95817f23",
395		Name:      "example-lb-01",
396		Algorithm: "round_robin",
397		Status:    "new",
398		Created:   "2016-12-15T14:19:09Z",
399		ForwardingRules: []ForwardingRule{
400			{
401				EntryProtocol:  "https",
402				EntryPort:      443,
403				TargetProtocol: "http",
404				TargetPort:     80,
405				CertificateID:  "a-b-c",
406				TlsPassthrough: false,
407			},
408			{
409				EntryProtocol:  "https",
410				EntryPort:      444,
411				TargetProtocol: "https",
412				TargetPort:     443,
413				CertificateID:  "",
414				TlsPassthrough: true,
415			},
416		},
417		HealthCheck: &HealthCheck{
418			Protocol:               "http",
419			Port:                   80,
420			Path:                   "/index.html",
421			CheckIntervalSeconds:   10,
422			ResponseTimeoutSeconds: 5,
423			HealthyThreshold:       5,
424			UnhealthyThreshold:     3,
425		},
426		StickySessions: &StickySessions{
427			Type:             "cookies",
428			CookieName:       "DO-LB",
429			CookieTtlSeconds: 5,
430		},
431		Region: &Region{
432			Slug:      "nyc1",
433			Name:      "New York 1",
434			Sizes:     []string{"512mb", "1gb", "2gb", "4gb", "8gb", "16gb"},
435			Available: true,
436			Features:  []string{"private_networking", "backups", "ipv6", "metadata", "storage"},
437		},
438		Tags:                []string{"my-tag"},
439		DropletIDs:          []int{2, 21},
440		RedirectHttpToHttps: true,
441	}
442
443	assert.Equal(t, expected, loadBalancer)
444}
445
446func TestLoadBalancers_Update(t *testing.T) {
447	setup()
448	defer teardown()
449
450	updateRequest := &LoadBalancerRequest{
451		Name:      "example-lb-01",
452		Algorithm: "least_connections",
453		Region:    "nyc1",
454		ForwardingRules: []ForwardingRule{
455			{
456				EntryProtocol:  "http",
457				EntryPort:      80,
458				TargetProtocol: "http",
459				TargetPort:     80,
460			},
461			{
462				EntryProtocol:  "https",
463				EntryPort:      443,
464				TargetProtocol: "http",
465				TargetPort:     80,
466				CertificateID:  "a-b-c",
467			},
468		},
469		HealthCheck: &HealthCheck{
470			Protocol:               "tcp",
471			Port:                   80,
472			Path:                   "",
473			CheckIntervalSeconds:   10,
474			ResponseTimeoutSeconds: 5,
475			UnhealthyThreshold:     3,
476			HealthyThreshold:       5,
477		},
478		StickySessions: &StickySessions{
479			Type: "none",
480		},
481		DropletIDs: []int{2, 21},
482	}
483
484	path := "/v2/load_balancers"
485	loadBalancerId := "8268a81c-fcf5-423e-a337-bbfe95817f23"
486	path = fmt.Sprintf("%s/%s", path, loadBalancerId)
487
488	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
489		v := new(LoadBalancerRequest)
490		err := json.NewDecoder(r.Body).Decode(v)
491		if err != nil {
492			t.Fatal(err)
493		}
494
495		testMethod(t, r, "PUT")
496		assert.Equal(t, updateRequest, v)
497
498		fmt.Fprint(w, lbUpdateJSONResponse)
499	})
500
501	loadBalancer, _, err := client.LoadBalancers.Update(ctx, loadBalancerId, updateRequest)
502	if err != nil {
503		t.Errorf("LoadBalancers.Update returned error: %v", err)
504	}
505
506	expected := &LoadBalancer{
507		ID:        "8268a81c-fcf5-423e-a337-bbfe95817f23",
508		Name:      "example-lb-01",
509		IP:        "12.34.56.78",
510		Algorithm: "least_connections",
511		Status:    "active",
512		Created:   "2016-12-15T14:19:09Z",
513		ForwardingRules: []ForwardingRule{
514			{
515				EntryProtocol:  "http",
516				EntryPort:      80,
517				TargetProtocol: "http",
518				TargetPort:     80,
519			},
520			{
521				EntryProtocol:  "https",
522				EntryPort:      443,
523				TargetProtocol: "http",
524				TargetPort:     80,
525				CertificateID:  "a-b-c",
526			},
527		},
528		HealthCheck: &HealthCheck{
529			Protocol:               "tcp",
530			Port:                   80,
531			Path:                   "",
532			CheckIntervalSeconds:   10,
533			ResponseTimeoutSeconds: 5,
534			UnhealthyThreshold:     3,
535			HealthyThreshold:       5,
536		},
537		StickySessions: &StickySessions{
538			Type: "none",
539		},
540		Region: &Region{
541			Slug:      "nyc1",
542			Name:      "New York 1",
543			Sizes:     []string{"512mb", "1gb", "2gb", "4gb", "8gb", "16gb"},
544			Available: true,
545			Features:  []string{"private_networking", "backups", "ipv6", "metadata", "storage"},
546		},
547		DropletIDs: []int{2, 21},
548	}
549
550	assert.Equal(t, expected, loadBalancer)
551}
552
553func TestLoadBalancers_List(t *testing.T) {
554	setup()
555	defer teardown()
556
557	path := "/v2/load_balancers"
558	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
559		testMethod(t, r, http.MethodGet)
560		fmt.Fprint(w, lbListJSONResponse)
561	})
562
563	loadBalancers, _, err := client.LoadBalancers.List(ctx, nil)
564
565	if err != nil {
566		t.Errorf("LoadBalancers.List returned error: %v", err)
567	}
568
569	expected := []LoadBalancer{
570		{
571			ID:        "37e6be88-01ec-4ec7-9bc6-a514d4719057",
572			Name:      "example-lb-01",
573			IP:        "46.214.185.203",
574			Algorithm: "round_robin",
575			Status:    "active",
576			Created:   "2016-12-15T14:16:36Z",
577			ForwardingRules: []ForwardingRule{
578				{
579					EntryProtocol:  "https",
580					EntryPort:      443,
581					TargetProtocol: "http",
582					TargetPort:     80,
583					CertificateID:  "a-b-c",
584				},
585			},
586			HealthCheck: &HealthCheck{
587				Protocol:               "http",
588				Port:                   80,
589				Path:                   "/index.html",
590				CheckIntervalSeconds:   10,
591				ResponseTimeoutSeconds: 5,
592				HealthyThreshold:       5,
593				UnhealthyThreshold:     3,
594			},
595			StickySessions: &StickySessions{
596				Type:             "cookies",
597				CookieName:       "DO-LB",
598				CookieTtlSeconds: 5,
599			},
600			Region: &Region{
601				Slug:      "nyc1",
602				Name:      "New York 1",
603				Sizes:     []string{"512mb", "1gb", "2gb", "4gb", "8gb", "16gb"},
604				Available: true,
605				Features:  []string{"private_networking", "backups", "ipv6", "metadata", "storage"},
606			},
607			DropletIDs: []int{2, 21},
608		},
609	}
610
611	assert.Equal(t, expected, loadBalancers)
612}
613
614func TestLoadBalancers_List_Pagination(t *testing.T) {
615	setup()
616	defer teardown()
617
618	path := "/v2/load_balancers"
619	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
620		testMethod(t, r, http.MethodGet)
621		testFormValues(t, r, map[string]string{"page": "2"})
622		fmt.Fprint(w, lbListJSONResponse)
623	})
624
625	opts := &ListOptions{Page: 2}
626	_, resp, err := client.LoadBalancers.List(ctx, opts)
627
628	if err != nil {
629		t.Errorf("LoadBalancers.List returned error: %v", err)
630	}
631
632	assert.Equal(t, "http://localhost:3001/v2/load_balancers?page=2&per_page=1", resp.Links.Pages.Next)
633	assert.Equal(t, "http://localhost:3001/v2/load_balancers?page=3&per_page=1", resp.Links.Pages.Last)
634}
635
636func TestLoadBalancers_Delete(t *testing.T) {
637	setup()
638	defer teardown()
639
640	lbID := "37e6be88-01ec-4ec7-9bc6-a514d4719057"
641	path := "/v2/load_balancers"
642	path = fmt.Sprintf("%s/%s", path, lbID)
643	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
644		testMethod(t, r, http.MethodDelete)
645	})
646
647	_, err := client.LoadBalancers.Delete(ctx, lbID)
648
649	if err != nil {
650		t.Errorf("LoadBalancers.Delete returned error: %v", err)
651	}
652}
653
654func TestLoadBalancers_AddDroplets(t *testing.T) {
655	setup()
656	defer teardown()
657
658	dropletIdsRequest := &dropletIDsRequest{
659		IDs: []int{42, 44},
660	}
661
662	lbID := "37e6be88-01ec-4ec7-9bc6-a514d4719057"
663	path := fmt.Sprintf("/v2/load_balancers/%s/droplets", lbID)
664	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
665		v := new(dropletIDsRequest)
666		err := json.NewDecoder(r.Body).Decode(v)
667		if err != nil {
668			t.Fatal(err)
669		}
670
671		testMethod(t, r, http.MethodPost)
672		assert.Equal(t, dropletIdsRequest, v)
673
674		fmt.Fprint(w, nil)
675	})
676
677	_, err := client.LoadBalancers.AddDroplets(ctx, lbID, dropletIdsRequest.IDs...)
678
679	if err != nil {
680		t.Errorf("LoadBalancers.AddDroplets returned error: %v", err)
681	}
682}
683
684func TestLoadBalancers_RemoveDroplets(t *testing.T) {
685	setup()
686	defer teardown()
687
688	dropletIdsRequest := &dropletIDsRequest{
689		IDs: []int{2, 21},
690	}
691
692	lbID := "37e6be88-01ec-4ec7-9bc6-a514d4719057"
693	path := fmt.Sprintf("/v2/load_balancers/%s/droplets", lbID)
694	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
695		v := new(dropletIDsRequest)
696		err := json.NewDecoder(r.Body).Decode(v)
697		if err != nil {
698			t.Fatal(err)
699		}
700
701		testMethod(t, r, http.MethodDelete)
702		assert.Equal(t, dropletIdsRequest, v)
703
704		fmt.Fprint(w, nil)
705	})
706
707	_, err := client.LoadBalancers.RemoveDroplets(ctx, lbID, dropletIdsRequest.IDs...)
708
709	if err != nil {
710		t.Errorf("LoadBalancers.RemoveDroplets returned error: %v", err)
711	}
712}
713
714func TestLoadBalancers_AddForwardingRules(t *testing.T) {
715	setup()
716	defer teardown()
717
718	frr := &forwardingRulesRequest{
719		Rules: []ForwardingRule{
720			{
721				EntryProtocol:  "https",
722				EntryPort:      444,
723				TargetProtocol: "http",
724				TargetPort:     81,
725				CertificateID:  "b2abc00f-d3c4-426c-9f0b-b2f7a3ff7527",
726			},
727			{
728				EntryProtocol:  "tcp",
729				EntryPort:      8080,
730				TargetProtocol: "tcp",
731				TargetPort:     8081,
732			},
733		},
734	}
735
736	lbID := "37e6be88-01ec-4ec7-9bc6-a514d4719057"
737	path := fmt.Sprintf("/v2/load_balancers/%s/forwarding_rules", lbID)
738	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
739		v := new(forwardingRulesRequest)
740		err := json.NewDecoder(r.Body).Decode(v)
741		if err != nil {
742			t.Fatal(err)
743		}
744
745		testMethod(t, r, http.MethodPost)
746		assert.Equal(t, frr, v)
747
748		fmt.Fprint(w, nil)
749	})
750
751	_, err := client.LoadBalancers.AddForwardingRules(ctx, lbID, frr.Rules...)
752
753	if err != nil {
754		t.Errorf("LoadBalancers.AddForwardingRules returned error: %v", err)
755	}
756}
757
758func TestLoadBalancers_RemoveForwardingRules(t *testing.T) {
759	setup()
760	defer teardown()
761
762	frr := &forwardingRulesRequest{
763		Rules: []ForwardingRule{
764			{
765				EntryProtocol:  "https",
766				EntryPort:      444,
767				TargetProtocol: "http",
768				TargetPort:     81,
769			},
770			{
771				EntryProtocol:  "tcp",
772				EntryPort:      8080,
773				TargetProtocol: "tcp",
774				TargetPort:     8081,
775			},
776		},
777	}
778
779	lbID := "37e6be88-01ec-4ec7-9bc6-a514d4719057"
780	path := fmt.Sprintf("/v2/load_balancers/%s/forwarding_rules", lbID)
781	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
782		v := new(forwardingRulesRequest)
783		err := json.NewDecoder(r.Body).Decode(v)
784		if err != nil {
785			t.Fatal(err)
786		}
787
788		testMethod(t, r, http.MethodDelete)
789		assert.Equal(t, frr, v)
790
791		fmt.Fprint(w, nil)
792	})
793
794	_, err := client.LoadBalancers.RemoveForwardingRules(ctx, lbID, frr.Rules...)
795
796	if err != nil {
797		t.Errorf("LoadBalancers.RemoveForwardingRules returned error: %v", err)
798	}
799}
800
801func TestLoadBalancers_AsRequest(t *testing.T) {
802	lb := &LoadBalancer{
803		ID:        "37e6be88-01ec-4ec7-9bc6-a514d4719057",
804		Name:      "test-loadbalancer",
805		IP:        "10.0.0.1",
806		Algorithm: "least_connections",
807		Status:    "active",
808		Created:   "2011-06-24T12:00:00Z",
809		HealthCheck: &HealthCheck{
810			Protocol:               "http",
811			Port:                   80,
812			Path:                   "/ping",
813			CheckIntervalSeconds:   30,
814			ResponseTimeoutSeconds: 10,
815			HealthyThreshold:       3,
816			UnhealthyThreshold:     3,
817		},
818		StickySessions: &StickySessions{
819			Type:             "cookies",
820			CookieName:       "nomnom",
821			CookieTtlSeconds: 32,
822		},
823		Region: &Region{
824			Slug: "lon1",
825		},
826		RedirectHttpToHttps: true,
827	}
828	lb.DropletIDs = make([]int, 1, 2)
829	lb.DropletIDs[0] = 12345
830	lb.ForwardingRules = make([]ForwardingRule, 1, 2)
831	lb.ForwardingRules[0] = ForwardingRule{
832		EntryProtocol:  "http",
833		EntryPort:      80,
834		TargetProtocol: "http",
835		TargetPort:     80,
836	}
837
838	want := &LoadBalancerRequest{
839		Name:      "test-loadbalancer",
840		Algorithm: "least_connections",
841		Region:    "lon1",
842		ForwardingRules: []ForwardingRule{ForwardingRule{
843			EntryProtocol:  "http",
844			EntryPort:      80,
845			TargetProtocol: "http",
846			TargetPort:     80,
847		}},
848		HealthCheck: &HealthCheck{
849			Protocol:               "http",
850			Port:                   80,
851			Path:                   "/ping",
852			CheckIntervalSeconds:   30,
853			ResponseTimeoutSeconds: 10,
854			HealthyThreshold:       3,
855			UnhealthyThreshold:     3,
856		},
857		StickySessions: &StickySessions{
858			Type:             "cookies",
859			CookieName:       "nomnom",
860			CookieTtlSeconds: 32,
861		},
862		DropletIDs:          []int{12345},
863		RedirectHttpToHttps: true,
864	}
865
866	r := lb.AsRequest()
867	assert.Equal(t, want, r)
868	assert.False(t, r.HealthCheck == lb.HealthCheck, "HealthCheck points to same struct")
869	assert.False(t, r.StickySessions == lb.StickySessions, "StickySessions points to same struct")
870
871	r.DropletIDs = append(r.DropletIDs, 54321)
872	r.ForwardingRules = append(r.ForwardingRules, ForwardingRule{
873		EntryProtocol:  "https",
874		EntryPort:      443,
875		TargetProtocol: "https",
876		TargetPort:     443,
877		TlsPassthrough: true,
878	})
879
880	// Check that original LoadBalancer hasn't changed
881	lb.DropletIDs = append(lb.DropletIDs, 13579)
882	lb.ForwardingRules = append(lb.ForwardingRules, ForwardingRule{
883		EntryProtocol:  "tcp",
884		EntryPort:      587,
885		TargetProtocol: "tcp",
886		TargetPort:     587,
887	})
888	assert.Equal(t, []int{12345, 54321}, r.DropletIDs)
889	assert.Equal(t, []ForwardingRule{
890		ForwardingRule{
891			EntryProtocol:  "http",
892			EntryPort:      80,
893			TargetProtocol: "http",
894			TargetPort:     80,
895		},
896		ForwardingRule{
897			EntryProtocol:  "https",
898			EntryPort:      443,
899			TargetProtocol: "https",
900			TargetPort:     443,
901			TlsPassthrough: true,
902		},
903	}, r.ForwardingRules)
904}
905