Adding list nodes operation
diff --git a/rackspace/lb/v1/nodes/fixtures.go b/rackspace/lb/v1/nodes/fixtures.go
index 0969561..77be3b6 100644
--- a/rackspace/lb/v1/nodes/fixtures.go
+++ b/rackspace/lb/v1/nodes/fixtures.go
@@ -10,8 +10,12 @@
fake "github.com/rackspace/gophercloud/testhelper/client"
)
-func mockListResponse(t *testing.T) {
- th.Mux.HandleFunc("/loadbalancers", func(w http.ResponseWriter, r *http.Request) {
+func _rootURL(lbID int) string {
+ return "/loadbalancers/" + strconv.Itoa(lbID) + "/nodes"
+}
+
+func mockListResponse(t *testing.T, lbID int) {
+ th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "GET")
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
@@ -22,7 +26,7 @@
{
"nodes": [
{
- "id": "410",
+ "id": 410,
"address": "10.1.1.1",
"port": 80,
"condition": "ENABLED",
@@ -31,7 +35,7 @@
"type": "PRIMARY"
},
{
- "id": "411",
+ "id": 411,
"address": "10.1.1.2",
"port": 80,
"condition": "ENABLED",
diff --git a/rackspace/lb/v1/nodes/requests.go b/rackspace/lb/v1/nodes/requests.go
index 970f7f0..6e723d2 100644
--- a/rackspace/lb/v1/nodes/requests.go
+++ b/rackspace/lb/v1/nodes/requests.go
@@ -1 +1,21 @@
package nodes
+
+import (
+ "fmt"
+
+ "github.com/rackspace/gophercloud"
+ "github.com/rackspace/gophercloud/pagination"
+)
+
+func List(client *gophercloud.ServiceClient, loadBalancerID int, limit *int) pagination.Pager {
+ url := rootURL(client, loadBalancerID)
+
+ if limit != nil {
+ url += fmt.Sprintf("?limit=%d", limit)
+ }
+
+ createPageFn := func(r pagination.PageResult) pagination.Page {
+ return NodePage{pagination.SinglePageBase(r)}
+ }
+ return pagination.NewPager(client, url, createPageFn)
+}
diff --git a/rackspace/lb/v1/nodes/requests_test.go b/rackspace/lb/v1/nodes/requests_test.go
index 970f7f0..0509670 100644
--- a/rackspace/lb/v1/nodes/requests_test.go
+++ b/rackspace/lb/v1/nodes/requests_test.go
@@ -1 +1,57 @@
package nodes
+
+import (
+ "testing"
+
+ "github.com/rackspace/gophercloud/pagination"
+ th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/rackspace/gophercloud/testhelper/client"
+)
+
+const (
+ lbID = 12345
+ nodeID = 67890
+)
+
+func TestList(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ mockListResponse(t, lbID)
+
+ count := 0
+
+ err := List(client.ServiceClient(), lbID, nil).EachPage(func(page pagination.Page) (bool, error) {
+ count++
+ actual, err := ExtractNodes(page)
+ th.AssertNoErr(t, err)
+
+ expected := []Node{
+ Node{
+ ID: 410,
+ Address: "10.1.1.1",
+ Port: 80,
+ Condition: ENABLED,
+ Status: ONLINE,
+ Weight: 3,
+ Type: PRIMARY,
+ },
+ Node{
+ ID: 411,
+ Address: "10.1.1.2",
+ Port: 80,
+ Condition: ENABLED,
+ Status: ONLINE,
+ Weight: 8,
+ Type: SECONDARY,
+ },
+ }
+
+ th.CheckDeepEquals(t, expected, actual)
+
+ return true, nil
+ })
+
+ th.AssertNoErr(t, err)
+ th.AssertEquals(t, 1, count)
+}
diff --git a/rackspace/lb/v1/nodes/results.go b/rackspace/lb/v1/nodes/results.go
index d32fa77..98cb741 100644
--- a/rackspace/lb/v1/nodes/results.go
+++ b/rackspace/lb/v1/nodes/results.go
@@ -1,5 +1,11 @@
package nodes
+import (
+ "github.com/mitchellh/mapstructure"
+
+ "github.com/rackspace/gophercloud/pagination"
+)
+
// Node represents a back-end device, usually a virtual machine, that can
// handle traffic. It is assigned traffic based on its parent load balancer.
type Node struct {
@@ -16,7 +22,7 @@
Status Status
// The node's condition.
- Condition string
+ Condition Condition
// The priority at which this node will receive traffic if a weighted
// algorithm is used by its parent load balancer. Ranges from 1 to 100.
@@ -76,3 +82,31 @@
// satisfied with the node's response time.
OFFLINE Status = "OFFLINE"
)
+
+// NodePage is the page returned by a pager when traversing over a collection
+// of nodes.
+type NodePage struct {
+ pagination.SinglePageBase
+}
+
+// IsEmpty checks whether a NodePage struct is empty.
+func (p NodePage) IsEmpty() (bool, error) {
+ is, err := ExtractNodes(p)
+ if err != nil {
+ return true, nil
+ }
+ return len(is) == 0, nil
+}
+
+// ExtractNodes accepts a Page struct, specifically a NodePage struct, and
+// extracts the elements into a slice of Node structs. In other words, a
+// generic collection is mapped into a relevant slice.
+func ExtractNodes(page pagination.Page) ([]Node, error) {
+ var resp struct {
+ Nodes []Node `mapstructure:"nodes" json:"nodes"`
+ }
+
+ err := mapstructure.Decode(page.(NodePage).Body, &resp)
+
+ return resp.Nodes, err
+}
diff --git a/rackspace/lb/v1/nodes/urls.go b/rackspace/lb/v1/nodes/urls.go
index 970f7f0..d2ae7c3 100644
--- a/rackspace/lb/v1/nodes/urls.go
+++ b/rackspace/lb/v1/nodes/urls.go
@@ -1 +1,20 @@
package nodes
+
+import (
+ "strconv"
+
+ "github.com/rackspace/gophercloud"
+)
+
+const (
+ lbPath = "loadbalancers"
+ nodePath = "nodes"
+)
+
+func resourceURL(c *gophercloud.ServiceClient, lbID, nodeID int) string {
+ return c.ServiceURL(lbPath, strconv.Itoa(lbID), nodePath, strconv.Itoa(nodeID))
+}
+
+func rootURL(c *gophercloud.ServiceClient, lbID int) string {
+ return c.ServiceURL(lbPath, strconv.Itoa(lbID), nodePath)
+}