Finishing documentation
diff --git a/openstack/networking/v2/networks/doc.go b/openstack/networking/v2/networks/doc.go
index 83c4a6a..c87a7ce 100644
--- a/openstack/networking/v2/networks/doc.go
+++ b/openstack/networking/v2/networks/doc.go
@@ -1 +1,9 @@
+// Package networks contains functionality for working with Neutron network
+// resources. A network is an isolated virtual layer-2 broadcast domain that is
+// typically reserved for the tenant who created it (unless you configure the
+// network to be shared). Tenants can create multiple networks until the
+// thresholds per-tenant quota is reached.
+//
+// In the v2.0 Networking API, the network is the main entity. Ports and subnets
+// are always associated with a network.
package networks
diff --git a/openstack/networking/v2/networks/errors.go b/openstack/networking/v2/networks/errors.go
index 7a67ef7..83c4a6a 100644
--- a/openstack/networking/v2/networks/errors.go
+++ b/openstack/networking/v2/networks/errors.go
@@ -1,16 +1 @@
package networks
-
-import "fmt"
-
-func requiredAttr(attr string) error {
- return fmt.Errorf("You must specify %s for this resource", attr)
-}
-
-func err(str string) error {
- return fmt.Errorf("%s", str)
-}
-
-var (
- ErrNameRequired = requiredAttr("name")
- ErrNoURLFound = err("Next URL could not be extracted from collection")
-)
diff --git a/openstack/networking/v2/networks/requests.go b/openstack/networking/v2/networks/requests.go
index 4f1037e..f4fbe97 100644
--- a/openstack/networking/v2/networks/requests.go
+++ b/openstack/networking/v2/networks/requests.go
@@ -9,20 +9,6 @@
"github.com/rackspace/gophercloud/pagination"
)
-type ListOpts struct {
- Status string
- Name string
- AdminStateUp *bool
- TenantID string
- Shared *bool
- ID string
- Page int
- PerPage int
- Limit int
- SortKey string
- SortDir string
-}
-
type networkOpts struct {
AdminStateUp bool
Name string
@@ -40,6 +26,27 @@
}
}
+// ListOpts allows the filtering and sorting of paginated collections through
+// the API. Filtering is achieved by passing in struct field values that map to
+// the network attributes you want to see returned. SortKey allows you to sort
+// by a particular network attribute. SortDir sets the direction, and is either
+// `asc' or `desc'. Marker and Limit are used for pagination.
+type ListOpts struct {
+ Status string
+ Name string
+ AdminStateUp *bool
+ TenantID string
+ Shared *bool
+ ID string
+ Marker string
+ Limit int
+ SortKey string
+ SortDir string
+}
+
+// List returns a Pager which allows you to iterate over a collection of
+// networks. It accepts a ListOpts struct, which allows you to filter and sort
+// the returned collection for greater efficiency.
func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
// Build query parameters
q := make(map[string]string)
@@ -61,11 +68,8 @@
if opts.ID != "" {
q["id"] = opts.ID
}
- if opts.Page != 0 {
- q["page"] = strconv.Itoa(opts.Page)
- }
- if opts.PerPage != 0 {
- q["per_page"] = strconv.Itoa(opts.PerPage)
+ if opts.Marker != "" {
+ q["marker"] = opts.Marker
}
if opts.Limit != 0 {
q["limit"] = strconv.Itoa(opts.Limit)
@@ -77,15 +81,16 @@
q["sort_dir"] = opts.SortDir
}
- u := ListURL(c) + utils.BuildQuery(q)
+ u := listURL(c) + utils.BuildQuery(q)
return pagination.NewPager(c, u, func(r pagination.LastHTTPResponse) pagination.Page {
return NetworkPage{pagination.LinkedPageBase(r)}
})
}
+// Get retrieves a specific network based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) (*Network, error) {
var n Network
- _, err := perigee.Request("GET", GetURL(c, id), perigee.Options{
+ _, err := perigee.Request("GET", getURL(c, id), perigee.Options{
MoreHeaders: c.Provider.AuthenticatedHeaders(),
Results: &struct {
Network *Network `json:"network"`
@@ -98,13 +103,21 @@
return &n, nil
}
+// CreateOpts represents the attributes used when creating a new network.
type CreateOpts networkOpts
+// Create accepts a CreateOpts struct and creates a new network using the values
+// provided. This operation does not actually require a request body, i.e. the
+// CreateOpts struct argument can be empty.
+//
+// The tenant ID that is contained in the URI is the tenant that creates the
+// network. An admin user, however, has the option of specifying another tenant
+// ID in the CreateOpts struct.
func Create(c *gophercloud.ServiceClient, opts CreateOpts) (*NetworkCreateResult, error) {
// Define structures
type network struct {
- AdminStateUp bool `json:"admin_state_up"`
- Name string `json:"name"`
+ AdminStateUp bool `json:"admin_state_up,omitempty"`
+ Name string `json:"name,omitempty"`
Shared *bool `json:"shared,omitempty"`
TenantID *string `json:"tenant_id,omitempty"`
}
@@ -115,11 +128,6 @@
Network *NetworkCreateResult `json:"network"`
}
- // Validate
- if opts.Name == "" {
- return nil, ErrNameRequired
- }
-
// Populate request body
reqBody := request{Network: network{
AdminStateUp: opts.AdminStateUp,
@@ -133,7 +141,7 @@
// Send request to API
var res response
- _, err := perigee.Request("POST", CreateURL(c), perigee.Options{
+ _, err := perigee.Request("POST", createURL(c), perigee.Options{
MoreHeaders: c.Provider.AuthenticatedHeaders(),
ReqBody: &reqBody,
Results: &res,
@@ -146,8 +154,11 @@
return res.Network, nil
}
+// UpdateOpts represents the attributes used when updating an existing network.
type UpdateOpts networkOpts
+// Update accepts a UpdateOpts struct and updates an existing network using the
+// values provided. For more information, see the Create function.
func Update(c *gophercloud.ServiceClient, networkID string, opts UpdateOpts) (*Network, error) {
// Define structures
type network struct {
@@ -172,7 +183,7 @@
// Send request to API
var res response
- _, err := perigee.Request("PUT", GetURL(c, networkID), perigee.Options{
+ _, err := perigee.Request("PUT", getURL(c, networkID), perigee.Options{
MoreHeaders: c.Provider.AuthenticatedHeaders(),
ReqBody: &reqBody,
Results: &res,
@@ -185,8 +196,9 @@
return res.Network, nil
}
+// Delete accepts a unique ID and deletes the network associated with it.
func Delete(c *gophercloud.ServiceClient, networkID string) error {
- _, err := perigee.Request("DELETE", DeleteURL(c, networkID), perigee.Options{
+ _, err := perigee.Request("DELETE", deleteURL(c, networkID), perigee.Options{
MoreHeaders: c.Provider.AuthenticatedHeaders(),
OkCodes: []int{204},
})
diff --git a/openstack/networking/v2/networks/results.go b/openstack/networking/v2/networks/results.go
index 78bdff5..7f9e51a 100644
--- a/openstack/networking/v2/networks/results.go
+++ b/openstack/networking/v2/networks/results.go
@@ -5,12 +5,14 @@
"github.com/rackspace/gophercloud/pagination"
)
+// NetworkProvider represents provider extension data
type NetworkProvider struct {
ProviderSegmentationID int `json:"provider:segmentation_id"`
ProviderPhysicalNetwork string `json:"provider:physical_network"`
ProviderNetworkType string `json:"provider:network_type"`
}
+// Network represents, well, a network.
type Network struct {
// UUID for the network
ID string `mapstructure:"id" json:"id"`
@@ -34,17 +36,23 @@
RouterExternal bool `mapstructure:"router:external" json:"router:external"`
}
+// NetworkCreateResult represents what is returned by a create operation.
type NetworkCreateResult struct {
Network
Segments []NetworkProvider `json:"segments"`
PortSecurityEnabled bool `json:"port_security_enabled"`
}
+// NetworkPage is the page returned by a pager when traversing over a
+// collection of networks.
type NetworkPage struct {
pagination.LinkedPageBase
}
-func (current NetworkPage) NextPageURL() (string, error) {
+// NextPageURL is invoked when a paginated collection of networks has reached
+// the end of a page and the pager seeks to traverse over a new one. In order
+// to do this, it needs to construct the next page's URL.
+func (p NetworkPage) NextPageURL() (string, error) {
type link struct {
Href string `mapstructure:"href"`
Rel string `mapstructure:"rel"`
@@ -54,7 +62,7 @@
}
var r resp
- err := mapstructure.Decode(current.Body, &r)
+ err := mapstructure.Decode(p.Body, &r)
if err != nil {
return "", err
}
@@ -72,14 +80,18 @@
return url, nil
}
-func (r NetworkPage) IsEmpty() (bool, error) {
- is, err := ExtractNetworks(r)
+// IsEmpty checks whether a NetworkPage struct is empty.
+func (p NetworkPage) IsEmpty() (bool, error) {
+ is, err := ExtractNetworks(p)
if err != nil {
return true, nil
}
return len(is) == 0, nil
}
+// ExtractNetworks accepts a Page struct, specifically a NetworkPage struct,
+// and extracts the elements into a slice of Network structs. In other words,
+// a generic collection is mapped into a relevant slice.
func ExtractNetworks(page pagination.Page) ([]Network, error) {
var resp struct {
Networks []Network `mapstructure:"networks" json:"networks"`
diff --git a/openstack/networking/v2/networks/urls.go b/openstack/networking/v2/networks/urls.go
index a0d660a..80c307c 100644
--- a/openstack/networking/v2/networks/urls.go
+++ b/openstack/networking/v2/networks/urls.go
@@ -4,26 +4,26 @@
const Version = "v2.0"
-func ResourceURL(c *gophercloud.ServiceClient, id string) string {
+func resourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(Version, "networks", id)
}
-func RootURL(c *gophercloud.ServiceClient) string {
+func rootURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL(Version, "networks")
}
-func GetURL(c *gophercloud.ServiceClient, id string) string {
- return ResourceURL(c, id)
+func getURL(c *gophercloud.ServiceClient, id string) string {
+ return resourceURL(c, id)
}
-func ListURL(c *gophercloud.ServiceClient) string {
- return RootURL(c)
+func listURL(c *gophercloud.ServiceClient) string {
+ return rootURL(c)
}
-func CreateURL(c *gophercloud.ServiceClient) string {
- return RootURL(c)
+func createURL(c *gophercloud.ServiceClient) string {
+ return rootURL(c)
}
-func DeleteURL(c *gophercloud.ServiceClient, id string) string {
- return ResourceURL(c, id)
+func deleteURL(c *gophercloud.ServiceClient, id string) string {
+ return resourceURL(c, id)
}
diff --git a/openstack/networking/v2/networks/urls_test.go b/openstack/networking/v2/networks/urls_test.go
index 84a7ae6..713a547 100644
--- a/openstack/networking/v2/networks/urls_test.go
+++ b/openstack/networking/v2/networks/urls_test.go
@@ -7,32 +7,32 @@
th "github.com/rackspace/gophercloud/testhelper"
)
-const Endpoint = "http://localhost:57909/"
+const endpoint = "http://localhost:57909/"
-func EndpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: Endpoint}
+func endpointClient() *gophercloud.ServiceClient {
+ return &gophercloud.ServiceClient{Endpoint: endpoint}
}
func TestGetURL(t *testing.T) {
- actual := GetURL(EndpointClient(), "foo")
- expected := Endpoint + "v2.0/networks/foo"
+ actual := getURL(endpointClient(), "foo")
+ expected := endpoint + "v2.0/networks/foo"
th.AssertEquals(t, expected, actual)
}
func TestCreateURL(t *testing.T) {
- actual := CreateURL(EndpointClient())
- expected := Endpoint + "v2.0/networks"
+ actual := createURL(endpointClient())
+ expected := endpoint + "v2.0/networks"
th.AssertEquals(t, expected, actual)
}
func TestListURL(t *testing.T) {
- actual := CreateURL(EndpointClient())
- expected := Endpoint + "v2.0/networks"
+ actual := createURL(endpointClient())
+ expected := endpoint + "v2.0/networks"
th.AssertEquals(t, expected, actual)
}
func TestDeleteURL(t *testing.T) {
- actual := DeleteURL(EndpointClient(), "foo")
- expected := Endpoint + "v2.0/networks/foo"
+ actual := deleteURL(endpointClient(), "foo")
+ expected := endpoint + "v2.0/networks/foo"
th.AssertEquals(t, expected, actual)
}