Add AsRequest method on LoadBalancer

Updating a LoadBalancer requires a LoadBalancerRequest, which is not
easily creatable from a LoadBalancer.

Serializing the LoadBalancer to JSON and then deserializing it to a
LoadBalancerRequest mostly works, except that Region is a string on
the Request but not on the LB (since the LB returns the entire
Region object), so json.Unmarshal returns an error.

An explicit AsRequest method makes it easier for consumers of the API
to modify existing LoadBalancer objects, and is designed to avoid
modifying attributes on the original LoadBalancer when the
LoadBalancerRequest is modified.
This commit is contained in:
Luke Granger-Brown 2017-07-22 14:37:42 +01:00
parent 3484038586
commit 6dfa314396
No known key found for this signature in database
GPG Key ID: F665F13E25CF8D09
2 changed files with 141 additions and 10 deletions

View File

@ -48,6 +48,32 @@ func (l LoadBalancer) String() string {
return Stringify(l)
}
// AsRequest creates a LoadBalancerRequest that can be submitted to Update with the current values of the LoadBalancer.
// Modifying the returned LoadBalancerRequest will not modify the original LoadBalancer.
func (l LoadBalancer) AsRequest() *LoadBalancerRequest {
r := LoadBalancerRequest{
Name: l.Name,
Algorithm: l.Algorithm,
ForwardingRules: append([]ForwardingRule(nil), l.ForwardingRules...),
DropletIDs: append([]int(nil), l.DropletIDs...),
Tag: l.Tag,
RedirectHttpToHttps: l.RedirectHttpToHttps,
HealthCheck: l.HealthCheck,
}
if l.HealthCheck != nil {
r.HealthCheck = &HealthCheck{}
*r.HealthCheck = *l.HealthCheck
}
if l.StickySessions != nil {
r.StickySessions = &StickySessions{}
*r.StickySessions = *l.StickySessions
}
if l.Region != nil {
r.Region = l.Region.Slug
}
return &r
}
// ForwardingRule represents load balancer forwarding rules.
type ForwardingRule struct {
EntryProtocol string `json:"entry_protocol,omitempty"`

View File

@ -272,7 +272,7 @@ var lbUpdateJSONResponse = `
}
`
func TestLoadBlanacers_Get(t *testing.T) {
func TestLoadBalancers_Get(t *testing.T) {
setup()
defer teardown()
@ -333,7 +333,7 @@ func TestLoadBlanacers_Get(t *testing.T) {
assert.Equal(t, expected, loadBalancer)
}
func TestLoadBlanacers_Create(t *testing.T) {
func TestLoadBalancers_Create(t *testing.T) {
setup()
defer teardown()
@ -440,7 +440,7 @@ func TestLoadBlanacers_Create(t *testing.T) {
assert.Equal(t, expected, loadBalancer)
}
func TestLoadBlanacers_Update(t *testing.T) {
func TestLoadBalancers_Update(t *testing.T) {
setup()
defer teardown()
@ -547,7 +547,7 @@ func TestLoadBlanacers_Update(t *testing.T) {
assert.Equal(t, expected, loadBalancer)
}
func TestLoadBlanacers_List(t *testing.T) {
func TestLoadBalancers_List(t *testing.T) {
setup()
defer teardown()
@ -608,7 +608,7 @@ func TestLoadBlanacers_List(t *testing.T) {
assert.Equal(t, expected, loadBalancers)
}
func TestLoadBlanacers_List_Pagination(t *testing.T) {
func TestLoadBalancers_List_Pagination(t *testing.T) {
setup()
defer teardown()
@ -630,7 +630,7 @@ func TestLoadBlanacers_List_Pagination(t *testing.T) {
assert.Equal(t, "http://localhost:3001/v2/load_balancers?page=3&per_page=1", resp.Links.Pages.Last)
}
func TestLoadBlanacers_Delete(t *testing.T) {
func TestLoadBalancers_Delete(t *testing.T) {
setup()
defer teardown()
@ -648,7 +648,7 @@ func TestLoadBlanacers_Delete(t *testing.T) {
}
}
func TestLoadBlanacers_AddDroplets(t *testing.T) {
func TestLoadBalancers_AddDroplets(t *testing.T) {
setup()
defer teardown()
@ -678,7 +678,7 @@ func TestLoadBlanacers_AddDroplets(t *testing.T) {
}
}
func TestLoadBlanacers_RemoveDroplets(t *testing.T) {
func TestLoadBalancers_RemoveDroplets(t *testing.T) {
setup()
defer teardown()
@ -708,7 +708,7 @@ func TestLoadBlanacers_RemoveDroplets(t *testing.T) {
}
}
func TestLoadBlanacers_AddForwardingRules(t *testing.T) {
func TestLoadBalancers_AddForwardingRules(t *testing.T) {
setup()
defer teardown()
@ -752,7 +752,7 @@ func TestLoadBlanacers_AddForwardingRules(t *testing.T) {
}
}
func TestLoadBlanacers_RemoveForwardingRules(t *testing.T) {
func TestLoadBalancers_RemoveForwardingRules(t *testing.T) {
setup()
defer teardown()
@ -794,3 +794,108 @@ func TestLoadBlanacers_RemoveForwardingRules(t *testing.T) {
t.Errorf("LoadBalancers.RemoveForwardingRules returned error: %v", err)
}
}
func TestLoadBalancers_AsRequest(t *testing.T) {
lb := &LoadBalancer{
ID: "37e6be88-01ec-4ec7-9bc6-a514d4719057",
Name: "test-loadbalancer",
IP: "10.0.0.1",
Algorithm: "least_connections",
Status: "active",
Created: "2011-06-24T12:00:00Z",
HealthCheck: &HealthCheck{
Protocol: "http",
Port: 80,
Path: "/ping",
CheckIntervalSeconds: 30,
ResponseTimeoutSeconds: 10,
HealthyThreshold: 3,
UnhealthyThreshold: 3,
},
StickySessions: &StickySessions{
Type: "cookies",
CookieName: "nomnom",
CookieTtlSeconds: 32,
},
Region: &Region{
Slug: "lon1",
},
RedirectHttpToHttps: true,
}
lb.DropletIDs = make([]int, 1, 2)
lb.DropletIDs[0] = 12345
lb.ForwardingRules = make([]ForwardingRule, 1, 2)
lb.ForwardingRules[0] = ForwardingRule{
EntryProtocol: "http",
EntryPort: 80,
TargetProtocol: "http",
TargetPort: 80,
}
want := &LoadBalancerRequest{
Name: "test-loadbalancer",
Algorithm: "least_connections",
Region: "lon1",
ForwardingRules: []ForwardingRule{ForwardingRule{
EntryProtocol: "http",
EntryPort: 80,
TargetProtocol: "http",
TargetPort: 80,
}},
HealthCheck: &HealthCheck{
Protocol: "http",
Port: 80,
Path: "/ping",
CheckIntervalSeconds: 30,
ResponseTimeoutSeconds: 10,
HealthyThreshold: 3,
UnhealthyThreshold: 3,
},
StickySessions: &StickySessions{
Type: "cookies",
CookieName: "nomnom",
CookieTtlSeconds: 32,
},
DropletIDs: []int{12345},
RedirectHttpToHttps: true,
}
r := lb.AsRequest()
assert.Equal(t, want, r)
assert.False(t, r.HealthCheck == lb.HealthCheck, "HealthCheck points to same struct")
assert.False(t, r.StickySessions == lb.StickySessions, "StickySessions points to same struct")
r.DropletIDs = append(r.DropletIDs, 54321)
r.ForwardingRules = append(r.ForwardingRules, ForwardingRule{
EntryProtocol: "https",
EntryPort: 443,
TargetProtocol: "https",
TargetPort: 443,
TlsPassthrough: true,
})
// Check that original LoadBalancer hasn't changed
lb.DropletIDs = append(lb.DropletIDs, 13579)
lb.ForwardingRules = append(lb.ForwardingRules, ForwardingRule{
EntryProtocol: "tcp",
EntryPort: 587,
TargetProtocol: "tcp",
TargetPort: 587,
})
assert.Equal(t, []int{12345, 54321}, r.DropletIDs)
assert.Equal(t, []ForwardingRule{
ForwardingRule{
EntryProtocol: "http",
EntryPort: 80,
TargetProtocol: "http",
TargetPort: 80,
},
ForwardingRule{
EntryProtocol: "https",
EntryPort: 443,
TargetProtocol: "https",
TargetPort: 443,
TlsPassthrough: true,
},
}, r.ForwardingRules)
}