Update node
diff --git a/rackspace/lb/v1/nodes/fixtures.go b/rackspace/lb/v1/nodes/fixtures.go
index 3d0993c..2436664 100644
--- a/rackspace/lb/v1/nodes/fixtures.go
+++ b/rackspace/lb/v1/nodes/fixtures.go
@@ -163,13 +163,15 @@
th.TestJSONRequest(t, r, `
{
"node": {
- "condition": "ENABLED",
- "weight": 59
+ "address": "1.2.3.4",
+ "condition": "DRAINING",
+ "weight": 10,
+ "type": "SECONDARY"
}
}
`)
- w.WriteHeader(http.StatusOK)
+ w.WriteHeader(http.StatusAccepted)
})
}
diff --git a/rackspace/lb/v1/nodes/requests.go b/rackspace/lb/v1/nodes/requests.go
index 0ce8ca1..85d3fb1 100644
--- a/rackspace/lb/v1/nodes/requests.go
+++ b/rackspace/lb/v1/nodes/requests.go
@@ -33,6 +33,14 @@
Port int
Condition Condition
Type Type
+ Weight *int
+}
+
+func validateWeight(weight *int) error {
+ if weight != nil && (*weight > 100 || *weight < 0) {
+ return errors.New("Weight must be a valid int between 0 and 100")
+ }
+ return nil
}
func (opts CreateOpts) ToNodeCreateMap() (map[string]interface{}, error) {
@@ -43,6 +51,9 @@
if v.Address == "" {
return nodeMap{}, fmt.Errorf("ID is a required attribute, none provided for %d CreateOpt element", k)
}
+ if weightErr := validateWeight(v.Weight); weightErr != nil {
+ return nodeMap{}, weightErr
+ }
node := make(map[string]interface{})
node["address"] = v.Address
@@ -56,6 +67,9 @@
if v.Type != "" {
node["type"] = v.Type
}
+ if v.Weight != nil {
+ node["weight"] = &v.Weight
+ }
nodes = append(nodes, node)
}
@@ -122,3 +136,58 @@
return res
}
+
+func IntToPointer(i int) *int {
+ return &i
+}
+
+type UpdateOptsBuilder interface {
+ ToNodeUpdateMap() (map[string]interface{}, error)
+}
+
+type UpdateOpts struct {
+ Address string
+ Condition Condition
+ Weight *int
+ Type Type
+}
+
+func (opts UpdateOpts) ToNodeUpdateMap() (map[string]interface{}, error) {
+ node := make(map[string]interface{})
+
+ if opts.Address != "" {
+ node["address"] = opts.Address
+ }
+ if opts.Condition != "" {
+ node["condition"] = opts.Condition
+ }
+ if opts.Weight != nil {
+ if weightErr := validateWeight(opts.Weight); weightErr != nil {
+ return node, weightErr
+ }
+ node["weight"] = &opts.Weight
+ }
+ if opts.Type != "" {
+ node["type"] = opts.Type
+ }
+
+ return map[string]interface{}{"node": node}, nil
+}
+
+func Update(c *gophercloud.ServiceClient, lbID, nodeID int, opts UpdateOptsBuilder) UpdateResult {
+ var res UpdateResult
+
+ reqBody, err := opts.ToNodeUpdateMap()
+ if err != nil {
+ res.Err = err
+ return res
+ }
+
+ _, res.Err = perigee.Request("PUT", resourceURL(c, lbID, nodeID), perigee.Options{
+ MoreHeaders: c.AuthenticatedHeaders(),
+ ReqBody: &reqBody,
+ OkCodes: []int{202},
+ })
+
+ return res
+}
diff --git a/rackspace/lb/v1/nodes/requests_test.go b/rackspace/lb/v1/nodes/requests_test.go
index 5fdeadd..121cbee 100644
--- a/rackspace/lb/v1/nodes/requests_test.go
+++ b/rackspace/lb/v1/nodes/requests_test.go
@@ -140,3 +140,20 @@
th.AssertDeepEquals(t, expected, node)
}
+
+func TestUpdate(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ mockUpdateResponse(t, lbID, nodeID)
+
+ opts := UpdateOpts{
+ Address: "1.2.3.4",
+ Weight: IntToPointer(10),
+ Condition: DRAINING,
+ Type: SECONDARY,
+ }
+
+ err := Update(client.ServiceClient(), lbID, nodeID, opts).ExtractErr()
+ th.AssertNoErr(t, err)
+}
diff --git a/rackspace/lb/v1/nodes/results.go b/rackspace/lb/v1/nodes/results.go
index b514217..ca218f9 100644
--- a/rackspace/lb/v1/nodes/results.go
+++ b/rackspace/lb/v1/nodes/results.go
@@ -63,7 +63,7 @@
// DRAINING indicates that the node is allowed to service existing
// established connections and connections that are being directed to it as a
// result of the session persistence configuration.
- DRAINING
+ DRAINING Condition = "DRAINING"
)
// Status indicates whether the node can accept service traffic. If a node is
@@ -139,6 +139,10 @@
commonResult
}
+type UpdateResult struct {
+ gophercloud.ErrResult
+}
+
func (r commonResult) Extract() (*Node, error) {
if r.Err != nil {
return nil, r.Err