Update vendor dir and Godeps.json with new Godep

This commit is contained in:
saadali
2016-05-11 16:59:55 -07:00
parent b83af3d481
commit c708e2cc82
2053 changed files with 955 additions and 140589 deletions

View File

@@ -1,4 +0,0 @@
// Package apiversions provides information and interaction with the different
// API versions for the OpenStack Neutron service. This functionality is not
// restricted to this particular version.
package apiversions

View File

@@ -1 +0,0 @@
package apiversions

View File

@@ -1,21 +0,0 @@
package apiversions
import (
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// ListVersions lists all the Neutron API versions available to end-users
func ListVersions(c *gophercloud.ServiceClient) pagination.Pager {
return pagination.NewPager(c, apiVersionsURL(c), func(r pagination.PageResult) pagination.Page {
return APIVersionPage{pagination.SinglePageBase(r)}
})
}
// ListVersionResources lists all of the different API resources for a particular
// API versions. Typical resources for Neutron might be: networks, subnets, etc.
func ListVersionResources(c *gophercloud.ServiceClient, v string) pagination.Pager {
return pagination.NewPager(c, apiInfoURL(c, v), func(r pagination.PageResult) pagination.Page {
return APIVersionResourcePage{pagination.SinglePageBase(r)}
})
}

View File

@@ -1,77 +0,0 @@
package apiversions
import (
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud/pagination"
)
// APIVersion represents an API version for Neutron. It contains the status of
// the API, and its unique ID.
type APIVersion struct {
Status string `mapstructure:"status" json:"status"`
ID string `mapstructure:"id" json:"id"`
}
// APIVersionPage is the page returned by a pager when traversing over a
// collection of API versions.
type APIVersionPage struct {
pagination.SinglePageBase
}
// IsEmpty checks whether an APIVersionPage struct is empty.
func (r APIVersionPage) IsEmpty() (bool, error) {
is, err := ExtractAPIVersions(r)
if err != nil {
return true, err
}
return len(is) == 0, nil
}
// ExtractAPIVersions takes a collection page, extracts all of the elements,
// and returns them a slice of APIVersion structs. It is effectively a cast.
func ExtractAPIVersions(page pagination.Page) ([]APIVersion, error) {
var resp struct {
Versions []APIVersion `mapstructure:"versions"`
}
err := mapstructure.Decode(page.(APIVersionPage).Body, &resp)
return resp.Versions, err
}
// APIVersionResource represents a generic API resource. It contains the name
// of the resource and its plural collection name.
type APIVersionResource struct {
Name string `mapstructure:"name" json:"name"`
Collection string `mapstructure:"collection" json:"collection"`
}
// APIVersionResourcePage is a concrete type which embeds the common
// SinglePageBase struct, and is used when traversing API versions collections.
type APIVersionResourcePage struct {
pagination.SinglePageBase
}
// IsEmpty is a concrete function which indicates whether an
// APIVersionResourcePage is empty or not.
func (r APIVersionResourcePage) IsEmpty() (bool, error) {
is, err := ExtractVersionResources(r)
if err != nil {
return true, err
}
return len(is) == 0, nil
}
// ExtractVersionResources accepts a Page struct, specifically a
// APIVersionResourcePage struct, and extracts the elements into a slice of
// APIVersionResource structs. In other words, the collection is mapped into
// a relevant slice.
func ExtractVersionResources(page pagination.Page) ([]APIVersionResource, error) {
var resp struct {
APIVersionResources []APIVersionResource `mapstructure:"resources"`
}
err := mapstructure.Decode(page.(APIVersionResourcePage).Body, &resp)
return resp.APIVersionResources, err
}

View File

@@ -1,15 +0,0 @@
package apiversions
import (
"strings"
"github.com/rackspace/gophercloud"
)
func apiVersionsURL(c *gophercloud.ServiceClient) string {
return c.Endpoint
}
func apiInfoURL(c *gophercloud.ServiceClient, version string) string {
return c.Endpoint + strings.TrimRight(version, "/") + "/"
}

View File

@@ -1,14 +0,0 @@
package common
import (
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/testhelper/client"
)
const TokenID = client.TokenID
func ServiceClient() *gophercloud.ServiceClient {
sc := client.ServiceClient()
sc.ResourceBase = sc.Endpoint + "v2.0/"
return sc
}

View File

@@ -1,41 +0,0 @@
package extensions
import (
"github.com/rackspace/gophercloud"
common "github.com/rackspace/gophercloud/openstack/common/extensions"
"github.com/rackspace/gophercloud/pagination"
)
// Extension is a single OpenStack extension.
type Extension struct {
common.Extension
}
// GetResult wraps a GetResult from common.
type GetResult struct {
common.GetResult
}
// ExtractExtensions interprets a Page as a slice of Extensions.
func ExtractExtensions(page pagination.Page) ([]Extension, error) {
inner, err := common.ExtractExtensions(page)
if err != nil {
return nil, err
}
outer := make([]Extension, len(inner))
for index, ext := range inner {
outer[index] = Extension{ext}
}
return outer, nil
}
// Get retrieves information for a specific extension using its alias.
func Get(c *gophercloud.ServiceClient, alias string) GetResult {
return GetResult{common.Get(c, alias)}
}
// List returns a Pager which allows you to iterate over the full collection of extensions.
// It does not accept query parameters.
func List(c *gophercloud.ServiceClient) pagination.Pager {
return common.List(c)
}

View File

@@ -1,3 +0,0 @@
// Package external provides information and interaction with the external
// extension for the OpenStack Networking service.
package external

View File

@@ -1,69 +0,0 @@
package external
import (
"time"
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
)
// AdminState gives users a solid type to work with for create and update
// operations. It is recommended that users use the `Up` and `Down` enums.
type AdminState *bool
// Convenience vars for AdminStateUp values.
var (
iTrue = true
iFalse = false
Up AdminState = &iTrue
Down AdminState = &iFalse
)
// CreateOpts is the structure used when creating new external network
// resources. It embeds networks.CreateOpts and so inherits all of its required
// and optional fields, with the addition of the External field.
type CreateOpts struct {
Parent networks.CreateOpts
External bool
}
// ToNetworkCreateMap casts a CreateOpts struct to a map.
func (o CreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
// DO NOT REMOVE. Though this line seemingly does nothing of value, it is a
// splint to prevent the unit test from failing on Go Tip. We suspect it is a
// compiler issue that will hopefully be worked out prior to our next release.
// Again, for all the unit tests to pass, this line is necessary and sufficient
// at the moment. We should reassess after the Go 1.5 release to determine
// if this line is still needed.
time.Sleep(0 * time.Millisecond)
outer, err := o.Parent.ToNetworkCreateMap()
if err != nil {
return nil, err
}
outer["network"].(map[string]interface{})["router:external"] = o.External
return outer, nil
}
// UpdateOpts is the structure used when updating existing external network
// resources. It embeds networks.UpdateOpts and so inherits all of its required
// and optional fields, with the addition of the External field.
type UpdateOpts struct {
Parent networks.UpdateOpts
External bool
}
// ToNetworkUpdateMap casts an UpdateOpts struct to a map.
func (o UpdateOpts) ToNetworkUpdateMap() (map[string]interface{}, error) {
outer, err := o.Parent.ToNetworkUpdateMap()
if err != nil {
return nil, err
}
outer["network"].(map[string]interface{})["router:external"] = o.External
return outer, nil
}

View File

@@ -1,81 +0,0 @@
package external
import (
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
"github.com/rackspace/gophercloud/pagination"
)
// NetworkExternal represents a decorated form of a Network with based on the
// "external-net" extension.
type NetworkExternal struct {
// UUID for the network
ID string `mapstructure:"id" json:"id"`
// Human-readable name for the network. Might not be unique.
Name string `mapstructure:"name" json:"name"`
// The administrative state of network. If false (down), the network does not forward packets.
AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"`
// Indicates whether network is currently operational. Possible values include
// `ACTIVE', `DOWN', `BUILD', or `ERROR'. Plug-ins might define additional values.
Status string `mapstructure:"status" json:"status"`
// Subnets associated with this network.
Subnets []string `mapstructure:"subnets" json:"subnets"`
// Owner of network. Only admin users can specify a tenant_id other than its own.
TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
// Specifies whether the network resource can be accessed by any tenant or not.
Shared bool `mapstructure:"shared" json:"shared"`
// Specifies whether the network is an external network or not.
External bool `mapstructure:"router:external" json:"router:external"`
}
func commonExtract(e error, response interface{}) (*NetworkExternal, error) {
if e != nil {
return nil, e
}
var res struct {
Network *NetworkExternal `json:"network"`
}
err := mapstructure.Decode(response, &res)
return res.Network, err
}
// ExtractGet decorates a GetResult struct returned from a networks.Get()
// function with extended attributes.
func ExtractGet(r networks.GetResult) (*NetworkExternal, error) {
return commonExtract(r.Err, r.Body)
}
// ExtractCreate decorates a CreateResult struct returned from a networks.Create()
// function with extended attributes.
func ExtractCreate(r networks.CreateResult) (*NetworkExternal, error) {
return commonExtract(r.Err, r.Body)
}
// ExtractUpdate decorates a UpdateResult struct returned from a
// networks.Update() function with extended attributes.
func ExtractUpdate(r networks.UpdateResult) (*NetworkExternal, error) {
return commonExtract(r.Err, r.Body)
}
// ExtractList accepts a Page struct, specifically a NetworkPage struct, and
// extracts the elements into a slice of NetworkExternal structs. In other
// words, a generic collection is mapped into a relevant slice.
func ExtractList(page pagination.Page) ([]NetworkExternal, error) {
var resp struct {
Networks []NetworkExternal `mapstructure:"networks" json:"networks"`
}
err := mapstructure.Decode(page.(networks.NetworkPage).Body, &resp)
return resp.Networks, err
}

View File

@@ -1,3 +0,0 @@
// Package fwaas provides information and interaction with the Firewall
// as a Service extension for the OpenStack Networking service.
package fwaas

View File

@@ -1,11 +0,0 @@
package firewalls
import "fmt"
func err(str string) error {
return fmt.Errorf("%s", str)
}
var (
errPolicyRequired = err("A policy ID is required")
)

View File

@@ -1,216 +0,0 @@
package firewalls
import (
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// AdminState gives users a solid type to work with for create and update
// operations. It is recommended that users use the `Up` and `Down` enums.
type AdminState *bool
// Shared gives users a solid type to work with for create and update
// operations. It is recommended that users use the `Yes` and `No` enums.
type Shared *bool
// Convenience vars for AdminStateUp and Shared values.
var (
iTrue = true
iFalse = false
Up AdminState = &iTrue
Down AdminState = &iFalse
Yes Shared = &iTrue
No Shared = &iFalse
)
// ListOptsBuilder allows extensions to add additional parameters to the
// List request.
type ListOptsBuilder interface {
ToFirewallListQuery() (string, error)
}
// 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 firewall attributes you want to see returned. SortKey allows you to sort
// by a particular firewall attribute. SortDir sets the direction, and is either
// `asc' or `desc'. Marker and Limit are used for pagination.
type ListOpts struct {
TenantID string `q:"tenant_id"`
Name string `q:"name"`
Description string `q:"description"`
AdminStateUp bool `q:"admin_state_up"`
Shared bool `q:"shared"`
PolicyID string `q:"firewall_policy_id"`
ID string `q:"id"`
Limit int `q:"limit"`
Marker string `q:"marker"`
SortKey string `q:"sort_key"`
SortDir string `q:"sort_dir"`
}
// ToFirewallListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToFirewallListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return "", err
}
return q.String(), nil
}
// List returns a Pager which allows you to iterate over a collection of
// firewalls. It accepts a ListOpts struct, which allows you to filter
// and sort the returned collection for greater efficiency.
//
// Default policy settings return only those firewalls that are owned by the
// tenant who submits the request, unless an admin user submits the request.
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
url := rootURL(c)
if opts != nil {
query, err := opts.ToFirewallListQuery()
if err != nil {
return pagination.Pager{Err: err}
}
url += query
}
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
return FirewallPage{pagination.LinkedPageBase{PageResult: r}}
})
}
// CreateOptsBuilder is the interface options structs have to satisfy in order
// to be used in the main Create operation in this package. Since many
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type CreateOptsBuilder interface {
ToFirewallCreateMap() (map[string]interface{}, error)
}
// CreateOpts contains all the values needed to create a new firewall.
type CreateOpts struct {
// Only required if the caller has an admin role and wants to create a firewall
// for another tenant.
TenantID string
Name string
Description string
AdminStateUp *bool
Shared *bool
PolicyID string
}
// ToFirewallCreateMap casts a CreateOpts struct to a map.
func (opts CreateOpts) ToFirewallCreateMap() (map[string]interface{}, error) {
if opts.PolicyID == "" {
return nil, errPolicyRequired
}
f := make(map[string]interface{})
if opts.TenantID != "" {
f["tenant_id"] = opts.TenantID
}
if opts.Name != "" {
f["name"] = opts.Name
}
if opts.Description != "" {
f["description"] = opts.Description
}
if opts.Shared != nil {
f["shared"] = *opts.Shared
}
if opts.AdminStateUp != nil {
f["admin_state_up"] = *opts.AdminStateUp
}
if opts.PolicyID != "" {
f["firewall_policy_id"] = opts.PolicyID
}
return map[string]interface{}{"firewall": f}, nil
}
// Create accepts a CreateOpts struct and uses the values to create a new firewall
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
var res CreateResult
reqBody, err := opts.ToFirewallCreateMap()
if err != nil {
res.Err = err
return res
}
_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
return res
}
// Get retrieves a particular firewall based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) GetResult {
var res GetResult
_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
return res
}
// UpdateOptsBuilder is the interface options structs have to satisfy in order
// to be used in the main Update operation in this package. Since many
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type UpdateOptsBuilder interface {
ToFirewallUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts contains the values used when updating a firewall.
type UpdateOpts struct {
// Name of the firewall.
Name string
Description string
AdminStateUp *bool
Shared *bool
PolicyID string
}
// ToFirewallUpdateMap casts a CreateOpts struct to a map.
func (opts UpdateOpts) ToFirewallUpdateMap() (map[string]interface{}, error) {
f := make(map[string]interface{})
if opts.Name != "" {
f["name"] = opts.Name
}
if opts.Description != "" {
f["description"] = opts.Description
}
if opts.Shared != nil {
f["shared"] = *opts.Shared
}
if opts.AdminStateUp != nil {
f["admin_state_up"] = *opts.AdminStateUp
}
if opts.PolicyID != "" {
f["firewall_policy_id"] = opts.PolicyID
}
return map[string]interface{}{"firewall": f}, nil
}
// Update allows firewalls to be updated.
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
var res UpdateResult
reqBody, err := opts.ToFirewallUpdateMap()
if err != nil {
res.Err = err
return res
}
// Send request to API
_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
return res
}
// Delete will permanently delete a particular firewall based on its unique ID.
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
var res DeleteResult
_, res.Err = c.Delete(resourceURL(c, id), nil)
return res
}

View File

@@ -1,101 +0,0 @@
package firewalls
import (
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
type Firewall struct {
ID string `json:"id" mapstructure:"id"`
Name string `json:"name" mapstructure:"name"`
Description string `json:"description" mapstructure:"description"`
AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
Status string `json:"status" mapstructure:"status"`
PolicyID string `json:"firewall_policy_id" mapstructure:"firewall_policy_id"`
TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
}
type commonResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts a firewall.
func (r commonResult) Extract() (*Firewall, error) {
if r.Err != nil {
return nil, r.Err
}
var res struct {
Firewall *Firewall `json:"firewall"`
}
err := mapstructure.Decode(r.Body, &res)
return res.Firewall, err
}
// FirewallPage is the page returned by a pager when traversing over a
// collection of firewalls.
type FirewallPage struct {
pagination.LinkedPageBase
}
// NextPageURL is invoked when a paginated collection of firewalls 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 FirewallPage) NextPageURL() (string, error) {
type resp struct {
Links []gophercloud.Link `mapstructure:"firewalls_links"`
}
var r resp
err := mapstructure.Decode(p.Body, &r)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(r.Links)
}
// IsEmpty checks whether a FirewallPage struct is empty.
func (p FirewallPage) IsEmpty() (bool, error) {
is, err := ExtractFirewalls(p)
if err != nil {
return true, nil
}
return len(is) == 0, nil
}
// ExtractFirewalls accepts a Page struct, specifically a RouterPage struct,
// and extracts the elements into a slice of Router structs. In other words,
// a generic collection is mapped into a relevant slice.
func ExtractFirewalls(page pagination.Page) ([]Firewall, error) {
var resp struct {
Firewalls []Firewall `mapstructure:"firewalls" json:"firewalls"`
}
err := mapstructure.Decode(page.(FirewallPage).Body, &resp)
return resp.Firewalls, err
}
// GetResult represents the result of a get operation.
type GetResult struct {
commonResult
}
// UpdateResult represents the result of an update operation.
type UpdateResult struct {
commonResult
}
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
gophercloud.ErrResult
}
// CreateResult represents the result of a create operation.
type CreateResult struct {
commonResult
}

View File

@@ -1,16 +0,0 @@
package firewalls
import "github.com/rackspace/gophercloud"
const (
rootPath = "fw"
resourcePath = "firewalls"
)
func rootURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL(rootPath, resourcePath)
}
func resourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(rootPath, resourcePath, id)
}

View File

@@ -1,243 +0,0 @@
package policies
import (
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// Binary gives users a solid type to work with for create and update
// operations. It is recommended that users use the `Yes` and `No` enums
type Binary *bool
// Convenience vars for Audited and Shared values.
var (
iTrue = true
iFalse = false
Yes Binary = &iTrue
No Binary = &iFalse
)
// ListOptsBuilder allows extensions to add additional parameters to the
// List request.
type ListOptsBuilder interface {
ToPolicyListQuery() (string, error)
}
// 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 firewall policy attributes you want to see returned. SortKey allows you
// to sort by a particular firewall policy attribute. SortDir sets the direction,
// and is either `asc' or `desc'. Marker and Limit are used for pagination.
type ListOpts struct {
TenantID string `q:"tenant_id"`
Name string `q:"name"`
Description string `q:"description"`
Shared bool `q:"shared"`
Audited bool `q:"audited"`
ID string `q:"id"`
Limit int `q:"limit"`
Marker string `q:"marker"`
SortKey string `q:"sort_key"`
SortDir string `q:"sort_dir"`
}
// ToPolicyListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToPolicyListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return "", err
}
return q.String(), nil
}
// List returns a Pager which allows you to iterate over a collection of
// firewall policies. It accepts a ListOpts struct, which allows you to filter
// and sort the returned collection for greater efficiency.
//
// Default policy settings return only those firewall policies that are owned by the
// tenant who submits the request, unless an admin user submits the request.
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
url := rootURL(c)
if opts != nil {
query, err := opts.ToPolicyListQuery()
if err != nil {
return pagination.Pager{Err: err}
}
url += query
}
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
return PolicyPage{pagination.LinkedPageBase{PageResult: r}}
})
}
// CreateOptsBuilder is the interface options structs have to satisfy in order
// to be used in the main Create operation in this package. Since many
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type CreateOptsBuilder interface {
ToPolicyCreateMap() (map[string]interface{}, error)
}
// CreateOpts contains all the values needed to create a new firewall policy.
type CreateOpts struct {
// Only required if the caller has an admin role and wants to create a firewall policy
// for another tenant.
TenantID string
Name string
Description string
Shared *bool
Audited *bool
Rules []string
}
// ToPolicyCreateMap casts a CreateOpts struct to a map.
func (opts CreateOpts) ToPolicyCreateMap() (map[string]interface{}, error) {
p := make(map[string]interface{})
if opts.TenantID != "" {
p["tenant_id"] = opts.TenantID
}
if opts.Name != "" {
p["name"] = opts.Name
}
if opts.Description != "" {
p["description"] = opts.Description
}
if opts.Shared != nil {
p["shared"] = *opts.Shared
}
if opts.Audited != nil {
p["audited"] = *opts.Audited
}
if opts.Rules != nil {
p["firewall_rules"] = opts.Rules
}
return map[string]interface{}{"firewall_policy": p}, nil
}
// Create accepts a CreateOpts struct and uses the values to create a new firewall policy
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
var res CreateResult
reqBody, err := opts.ToPolicyCreateMap()
if err != nil {
res.Err = err
return res
}
_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
return res
}
// Get retrieves a particular firewall policy based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) GetResult {
var res GetResult
_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
return res
}
// UpdateOptsBuilder is the interface options structs have to satisfy in order
// to be used in the main Update operation in this package. Since many
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type UpdateOptsBuilder interface {
ToPolicyUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts contains the values used when updating a firewall policy.
type UpdateOpts struct {
// Name of the firewall policy.
Name string
Description string
Shared *bool
Audited *bool
Rules []string
}
// ToPolicyUpdateMap casts a CreateOpts struct to a map.
func (opts UpdateOpts) ToPolicyUpdateMap() (map[string]interface{}, error) {
p := make(map[string]interface{})
if opts.Name != "" {
p["name"] = opts.Name
}
if opts.Description != "" {
p["description"] = opts.Description
}
if opts.Shared != nil {
p["shared"] = *opts.Shared
}
if opts.Audited != nil {
p["audited"] = *opts.Audited
}
if opts.Rules != nil {
p["firewall_rules"] = opts.Rules
}
return map[string]interface{}{"firewall_policy": p}, nil
}
// Update allows firewall policies to be updated.
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
var res UpdateResult
reqBody, err := opts.ToPolicyUpdateMap()
if err != nil {
res.Err = err
return res
}
// Send request to API
_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
return res
}
// Delete will permanently delete a particular firewall policy based on its unique ID.
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
var res DeleteResult
_, res.Err = c.Delete(resourceURL(c, id), nil)
return res
}
func InsertRule(c *gophercloud.ServiceClient, policyID, ruleID, beforeID, afterID string) error {
type request struct {
RuleId string `json:"firewall_rule_id"`
Before string `json:"insert_before,omitempty"`
After string `json:"insert_after,omitempty"`
}
reqBody := request{
RuleId: ruleID,
Before: beforeID,
After: afterID,
}
// Send request to API
var res commonResult
_, res.Err = c.Put(insertURL(c, policyID), reqBody, &res.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
return res.Err
}
func RemoveRule(c *gophercloud.ServiceClient, policyID, ruleID string) error {
type request struct {
RuleId string `json:"firewall_rule_id"`
}
reqBody := request{
RuleId: ruleID,
}
// Send request to API
var res commonResult
_, res.Err = c.Put(removeURL(c, policyID), reqBody, &res.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
return res.Err
}

View File

@@ -1,101 +0,0 @@
package policies
import (
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
type Policy struct {
ID string `json:"id" mapstructure:"id"`
Name string `json:"name" mapstructure:"name"`
Description string `json:"description" mapstructure:"description"`
TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
Audited bool `json:"audited" mapstructure:"audited"`
Shared bool `json:"shared" mapstructure:"shared"`
Rules []string `json:"firewall_rules,omitempty" mapstructure:"firewall_rules"`
}
type commonResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts a firewall policy.
func (r commonResult) Extract() (*Policy, error) {
if r.Err != nil {
return nil, r.Err
}
var res struct {
Policy *Policy `json:"firewall_policy" mapstructure:"firewall_policy"`
}
err := mapstructure.Decode(r.Body, &res)
return res.Policy, err
}
// PolicyPage is the page returned by a pager when traversing over a
// collection of firewall policies.
type PolicyPage struct {
pagination.LinkedPageBase
}
// NextPageURL is invoked when a paginated collection of firewall policies 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 PolicyPage) NextPageURL() (string, error) {
type resp struct {
Links []gophercloud.Link `mapstructure:"firewall_policies_links"`
}
var r resp
err := mapstructure.Decode(p.Body, &r)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(r.Links)
}
// IsEmpty checks whether a PolicyPage struct is empty.
func (p PolicyPage) IsEmpty() (bool, error) {
is, err := ExtractPolicies(p)
if err != nil {
return true, nil
}
return len(is) == 0, nil
}
// ExtractPolicies accepts a Page struct, specifically a RouterPage struct,
// and extracts the elements into a slice of Router structs. In other words,
// a generic collection is mapped into a relevant slice.
func ExtractPolicies(page pagination.Page) ([]Policy, error) {
var resp struct {
Policies []Policy `mapstructure:"firewall_policies" json:"firewall_policies"`
}
err := mapstructure.Decode(page.(PolicyPage).Body, &resp)
return resp.Policies, err
}
// GetResult represents the result of a get operation.
type GetResult struct {
commonResult
}
// UpdateResult represents the result of an update operation.
type UpdateResult struct {
commonResult
}
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
gophercloud.ErrResult
}
// CreateResult represents the result of a create operation.
type CreateResult struct {
commonResult
}

View File

@@ -1,26 +0,0 @@
package policies
import "github.com/rackspace/gophercloud"
const (
rootPath = "fw"
resourcePath = "firewall_policies"
insertPath = "insert_rule"
removePath = "remove_rule"
)
func rootURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL(rootPath, resourcePath)
}
func resourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(rootPath, resourcePath, id)
}
func insertURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(rootPath, resourcePath, id, insertPath)
}
func removeURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(rootPath, resourcePath, id, removePath)
}

View File

@@ -1,12 +0,0 @@
package rules
import "fmt"
func err(str string) error {
return fmt.Errorf("%s", str)
}
var (
errProtocolRequired = err("A protocol is required (tcp, udp, icmp or any)")
errActionRequired = err("An action is required (allow or deny)")
)

View File

@@ -1,285 +0,0 @@
package rules
import (
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// Binary gives users a solid type to work with for create and update
// operations. It is recommended that users use the `Yes` and `No` enums
type Binary *bool
// Convenience vars for Enabled and Shared values.
var (
iTrue = true
iFalse = false
Yes Binary = &iTrue
No Binary = &iFalse
)
// ListOptsBuilder allows extensions to add additional parameters to the
// List request.
type ListOptsBuilder interface {
ToRuleListQuery() (string, error)
}
// 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 Firewall rule attributes you want to see returned. SortKey allows you to
// sort by a particular firewall rule attribute. SortDir sets the direction, and is
// either `asc' or `desc'. Marker and Limit are used for pagination.
type ListOpts struct {
TenantID string `q:"tenant_id"`
Name string `q:"name"`
Description string `q:"description"`
Protocol string `q:"protocol"`
Action string `q:"action"`
IPVersion int `q:"ip_version"`
SourceIPAddress string `q:"source_ip_address"`
DestinationIPAddress string `q:"destination_ip_address"`
SourcePort string `q:"source_port"`
DestinationPort string `q:"destination_port"`
Enabled bool `q:"enabled"`
ID string `q:"id"`
Limit int `q:"limit"`
Marker string `q:"marker"`
SortKey string `q:"sort_key"`
SortDir string `q:"sort_dir"`
}
// ToRuleListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToRuleListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return "", err
}
return q.String(), nil
}
// List returns a Pager which allows you to iterate over a collection of
// firewall rules. It accepts a ListOpts struct, which allows you to filter
// and sort the returned collection for greater efficiency.
//
// Default policy settings return only those firewall rules that are owned by the
// tenant who submits the request, unless an admin user submits the request.
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
url := rootURL(c)
if opts != nil {
query, err := opts.ToRuleListQuery()
if err != nil {
return pagination.Pager{Err: err}
}
url += query
}
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
return RulePage{pagination.LinkedPageBase{PageResult: r}}
})
}
// CreateOptsBuilder is the interface options structs have to satisfy in order
// to be used in the main Create operation in this package. Since many
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type CreateOptsBuilder interface {
ToRuleCreateMap() (map[string]interface{}, error)
}
// CreateOpts contains all the values needed to create a new firewall rule.
type CreateOpts struct {
// Mandatory for create
Protocol string
Action string
// Optional
TenantID string
Name string
Description string
IPVersion int
SourceIPAddress string
DestinationIPAddress string
SourcePort string
DestinationPort string
Shared *bool
Enabled *bool
}
// ToRuleCreateMap casts a CreateOpts struct to a map.
func (opts CreateOpts) ToRuleCreateMap() (map[string]interface{}, error) {
if opts.Protocol == "" {
return nil, errProtocolRequired
}
if opts.Action == "" {
return nil, errActionRequired
}
r := make(map[string]interface{})
r["protocol"] = opts.Protocol
r["action"] = opts.Action
if opts.TenantID != "" {
r["tenant_id"] = opts.TenantID
}
if opts.Name != "" {
r["name"] = opts.Name
}
if opts.Description != "" {
r["description"] = opts.Description
}
if opts.IPVersion != 0 {
r["ip_version"] = opts.IPVersion
}
if opts.SourceIPAddress != "" {
r["source_ip_address"] = opts.SourceIPAddress
}
if opts.DestinationIPAddress != "" {
r["destination_ip_address"] = opts.DestinationIPAddress
}
if opts.SourcePort != "" {
r["source_port"] = opts.SourcePort
}
if opts.DestinationPort != "" {
r["destination_port"] = opts.DestinationPort
}
if opts.Shared != nil {
r["shared"] = *opts.Shared
}
if opts.Enabled != nil {
r["enabled"] = *opts.Enabled
}
return map[string]interface{}{"firewall_rule": r}, nil
}
// Create accepts a CreateOpts struct and uses the values to create a new firewall rule
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
var res CreateResult
reqBody, err := opts.ToRuleCreateMap()
if err != nil {
res.Err = err
return res
}
_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
return res
}
// Get retrieves a particular firewall rule based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) GetResult {
var res GetResult
_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
return res
}
// UpdateOptsBuilder is the interface options structs have to satisfy in order
// to be used in the main Update operation in this package. Since many
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type UpdateOptsBuilder interface {
ToRuleUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts contains the values used when updating a firewall rule.
// Optional
type UpdateOpts struct {
Protocol string
Action string
Name string
Description string
IPVersion int
SourceIPAddress *string
DestinationIPAddress *string
SourcePort *string
DestinationPort *string
Shared *bool
Enabled *bool
}
// ToRuleUpdateMap casts a UpdateOpts struct to a map.
func (opts UpdateOpts) ToRuleUpdateMap() (map[string]interface{}, error) {
r := make(map[string]interface{})
if opts.Protocol != "" {
r["protocol"] = opts.Protocol
}
if opts.Action != "" {
r["action"] = opts.Action
}
if opts.Name != "" {
r["name"] = opts.Name
}
if opts.Description != "" {
r["description"] = opts.Description
}
if opts.IPVersion != 0 {
r["ip_version"] = opts.IPVersion
}
if opts.SourceIPAddress != nil {
s := *opts.SourceIPAddress
if s == "" {
r["source_ip_address"] = nil
} else {
r["source_ip_address"] = s
}
}
if opts.DestinationIPAddress != nil {
s := *opts.DestinationIPAddress
if s == "" {
r["destination_ip_address"] = nil
} else {
r["destination_ip_address"] = s
}
}
if opts.SourcePort != nil {
s := *opts.SourcePort
if s == "" {
r["source_port"] = nil
} else {
r["source_port"] = s
}
}
if opts.DestinationPort != nil {
s := *opts.DestinationPort
if s == "" {
r["destination_port"] = nil
} else {
r["destination_port"] = s
}
}
if opts.Shared != nil {
r["shared"] = *opts.Shared
}
if opts.Enabled != nil {
r["enabled"] = *opts.Enabled
}
return map[string]interface{}{"firewall_rule": r}, nil
}
// Update allows firewall policies to be updated.
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
var res UpdateResult
reqBody, err := opts.ToRuleUpdateMap()
if err != nil {
res.Err = err
return res
}
// Send request to API
_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
return res
}
// Delete will permanently delete a particular firewall rule based on its unique ID.
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
var res DeleteResult
_, res.Err = c.Delete(resourceURL(c, id), nil)
return res
}

View File

@@ -1,110 +0,0 @@
package rules
import (
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// Rule represents a firewall rule
type Rule struct {
ID string `json:"id" mapstructure:"id"`
Name string `json:"name,omitempty" mapstructure:"name"`
Description string `json:"description,omitempty" mapstructure:"description"`
Protocol string `json:"protocol" mapstructure:"protocol"`
Action string `json:"action" mapstructure:"action"`
IPVersion int `json:"ip_version,omitempty" mapstructure:"ip_version"`
SourceIPAddress string `json:"source_ip_address,omitempty" mapstructure:"source_ip_address"`
DestinationIPAddress string `json:"destination_ip_address,omitempty" mapstructure:"destination_ip_address"`
SourcePort string `json:"source_port,omitempty" mapstructure:"source_port"`
DestinationPort string `json:"destination_port,omitempty" mapstructure:"destination_port"`
Shared bool `json:"shared,omitempty" mapstructure:"shared"`
Enabled bool `json:"enabled,omitempty" mapstructure:"enabled"`
PolicyID string `json:"firewall_policy_id" mapstructure:"firewall_policy_id"`
Position int `json:"position" mapstructure:"position"`
TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
}
// RulePage is the page returned by a pager when traversing over a
// collection of firewall rules.
type RulePage struct {
pagination.LinkedPageBase
}
// NextPageURL is invoked when a paginated collection of firewall rules 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 RulePage) NextPageURL() (string, error) {
type resp struct {
Links []gophercloud.Link `mapstructure:"firewall_rules_links"`
}
var r resp
err := mapstructure.Decode(p.Body, &r)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(r.Links)
}
// IsEmpty checks whether a RulePage struct is empty.
func (p RulePage) IsEmpty() (bool, error) {
is, err := ExtractRules(p)
if err != nil {
return true, nil
}
return len(is) == 0, nil
}
// ExtractRules accepts a Page struct, specifically a RouterPage struct,
// and extracts the elements into a slice of Router structs. In other words,
// a generic collection is mapped into a relevant slice.
func ExtractRules(page pagination.Page) ([]Rule, error) {
var resp struct {
Rules []Rule `mapstructure:"firewall_rules" json:"firewall_rules"`
}
err := mapstructure.Decode(page.(RulePage).Body, &resp)
return resp.Rules, err
}
type commonResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts a firewall rule.
func (r commonResult) Extract() (*Rule, error) {
if r.Err != nil {
return nil, r.Err
}
var res struct {
Rule *Rule `json:"firewall_rule" mapstructure:"firewall_rule"`
}
err := mapstructure.Decode(r.Body, &res)
return res.Rule, err
}
// GetResult represents the result of a get operation.
type GetResult struct {
commonResult
}
// UpdateResult represents the result of an update operation.
type UpdateResult struct {
commonResult
}
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
gophercloud.ErrResult
}
// CreateResult represents the result of a create operation.
type CreateResult struct {
commonResult
}

View File

@@ -1,16 +0,0 @@
package rules
import "github.com/rackspace/gophercloud"
const (
rootPath = "fw"
resourcePath = "firewall_rules"
)
func rootURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL(rootPath, resourcePath)
}
func resourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(rootPath, resourcePath, id)
}

View File

@@ -1,5 +0,0 @@
// Package layer3 provides access to the Layer-3 networking extension for the
// OpenStack Neutron service. This extension allows API users to route packets
// between subnets, forward packets from internal networks to external ones,
// and access instances from external networks through floating IPs.
package layer3

View File

@@ -1,237 +0,0 @@
package routers
import (
"errors"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// 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 floating IP 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 {
ID string `q:"id"`
Name string `q:"name"`
AdminStateUp *bool `q:"admin_state_up"`
Distributed *bool `q:"distributed"`
Status string `q:"status"`
TenantID string `q:"tenant_id"`
Limit int `q:"limit"`
Marker string `q:"marker"`
SortKey string `q:"sort_key"`
SortDir string `q:"sort_dir"`
}
// List returns a Pager which allows you to iterate over a collection of
// routers. It accepts a ListOpts struct, which allows you to filter and sort
// the returned collection for greater efficiency.
//
// Default policy settings return only those routers that are owned by the
// tenant who submits the request, unless an admin user submits the request.
func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
q, err := gophercloud.BuildQueryString(&opts)
if err != nil {
return pagination.Pager{Err: err}
}
u := rootURL(c) + q.String()
return pagination.NewPager(c, u, func(r pagination.PageResult) pagination.Page {
return RouterPage{pagination.LinkedPageBase{PageResult: r}}
})
}
// CreateOpts contains all the values needed to create a new router. There are
// no required values.
type CreateOpts struct {
Name string
AdminStateUp *bool
Distributed *bool
TenantID string
GatewayInfo *GatewayInfo
}
// Create accepts a CreateOpts struct and uses the values to create a new
// logical router. When it is created, the router does not have an internal
// interface - it is not associated to any subnet.
//
// You can optionally specify an external gateway for a router using the
// GatewayInfo struct. The external gateway for the router must be plugged into
// an external network (it is external if its `router:external' field is set to
// true).
func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
type router struct {
Name *string `json:"name,omitempty"`
AdminStateUp *bool `json:"admin_state_up,omitempty"`
Distributed *bool `json:"distributed,omitempty"`
TenantID *string `json:"tenant_id,omitempty"`
GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"`
}
type request struct {
Router router `json:"router"`
}
reqBody := request{Router: router{
Name: gophercloud.MaybeString(opts.Name),
AdminStateUp: opts.AdminStateUp,
Distributed: opts.Distributed,
TenantID: gophercloud.MaybeString(opts.TenantID),
}}
if opts.GatewayInfo != nil {
reqBody.Router.GatewayInfo = opts.GatewayInfo
}
var res CreateResult
_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
return res
}
// Get retrieves a particular router based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) GetResult {
var res GetResult
_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
return res
}
// UpdateOpts contains the values used when updating a router.
type UpdateOpts struct {
Name string
AdminStateUp *bool
Distributed *bool
GatewayInfo *GatewayInfo
Routes []Route
}
// Update allows routers to be updated. You can update the name, administrative
// state, and the external gateway. For more information about how to set the
// external gateway for a router, see Create. This operation does not enable
// the update of router interfaces. To do this, use the AddInterface and
// RemoveInterface functions.
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
type router struct {
Name *string `json:"name,omitempty"`
AdminStateUp *bool `json:"admin_state_up,omitempty"`
Distributed *bool `json:"distributed,omitempty"`
GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"`
Routes []Route `json:"routes"`
}
type request struct {
Router router `json:"router"`
}
reqBody := request{Router: router{
Name: gophercloud.MaybeString(opts.Name),
AdminStateUp: opts.AdminStateUp,
Distributed: opts.Distributed,
}}
if opts.GatewayInfo != nil {
reqBody.Router.GatewayInfo = opts.GatewayInfo
}
if opts.Routes != nil {
reqBody.Router.Routes = opts.Routes
}
// Send request to API
var res UpdateResult
_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
return res
}
// Delete will permanently delete a particular router based on its unique ID.
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
var res DeleteResult
_, res.Err = c.Delete(resourceURL(c, id), nil)
return res
}
var errInvalidInterfaceOpts = errors.New("When adding a router interface you must provide either a subnet ID or a port ID")
// InterfaceOpts allow you to work with operations that either add or remote
// an internal interface from a router.
type InterfaceOpts struct {
SubnetID string
PortID string
}
// AddInterface attaches a subnet to an internal router interface. You must
// specify either a SubnetID or PortID in the request body. If you specify both,
// the operation will fail and an error will be returned.
//
// If you specify a SubnetID, the gateway IP address for that particular subnet
// is used to create the router interface. Alternatively, if you specify a
// PortID, the IP address associated with the port is used to create the router
// interface.
//
// If you reference a port that is associated with multiple IP addresses, or
// if the port is associated with zero IP addresses, the operation will fail and
// a 400 Bad Request error will be returned.
//
// If you reference a port already in use, the operation will fail and a 409
// Conflict error will be returned.
//
// The PortID that is returned after using Extract() on the result of this
// operation can either be the same PortID passed in or, on the other hand, the
// identifier of a new port created by this operation. After the operation
// completes, the device ID of the port is set to the router ID, and the
// device owner attribute is set to `network:router_interface'.
func AddInterface(c *gophercloud.ServiceClient, id string, opts InterfaceOpts) InterfaceResult {
var res InterfaceResult
// Validate
if (opts.SubnetID == "" && opts.PortID == "") || (opts.SubnetID != "" && opts.PortID != "") {
res.Err = errInvalidInterfaceOpts
return res
}
type request struct {
SubnetID string `json:"subnet_id,omitempty"`
PortID string `json:"port_id,omitempty"`
}
body := request{SubnetID: opts.SubnetID, PortID: opts.PortID}
_, res.Err = c.Put(addInterfaceURL(c, id), body, &res.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
return res
}
// RemoveInterface removes an internal router interface, which detaches a
// subnet from the router. You must specify either a SubnetID or PortID, since
// these values are used to identify the router interface to remove.
//
// Unlike AddInterface, you can also specify both a SubnetID and PortID. If you
// choose to specify both, the subnet ID must correspond to the subnet ID of
// the first IP address on the port specified by the port ID. Otherwise, the
// operation will fail and return a 409 Conflict error.
//
// If the router, subnet or port which are referenced do not exist or are not
// visible to you, the operation will fail and a 404 Not Found error will be
// returned. After this operation completes, the port connecting the router
// with the subnet is removed from the subnet for the network.
func RemoveInterface(c *gophercloud.ServiceClient, id string, opts InterfaceOpts) InterfaceResult {
var res InterfaceResult
type request struct {
SubnetID string `json:"subnet_id,omitempty"`
PortID string `json:"port_id,omitempty"`
}
body := request{SubnetID: opts.SubnetID, PortID: opts.PortID}
_, res.Err = c.Put(removeInterfaceURL(c, id), body, &res.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
return res
}

View File

@@ -1,171 +0,0 @@
package routers
import (
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// GatewayInfo represents the information of an external gateway for any
// particular network router.
type GatewayInfo struct {
NetworkID string `json:"network_id" mapstructure:"network_id"`
}
type Route struct {
NextHop string `mapstructure:"nexthop" json:"nexthop"`
DestinationCIDR string `mapstructure:"destination" json:"destination"`
}
// Router represents a Neutron router. A router is a logical entity that
// forwards packets across internal subnets and NATs (network address
// translation) them on external networks through an appropriate gateway.
//
// A router has an interface for each subnet with which it is associated. By
// default, the IP address of such interface is the subnet's gateway IP. Also,
// whenever a router is associated with a subnet, a port for that router
// interface is added to the subnet's network.
type Router struct {
// Indicates whether or not a router is currently operational.
Status string `json:"status" mapstructure:"status"`
// Information on external gateway for the router.
GatewayInfo GatewayInfo `json:"external_gateway_info" mapstructure:"external_gateway_info"`
// Administrative state of the router.
AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
// Whether router is disitrubted or not..
Distributed bool `json:"distributed" mapstructure:"distributed"`
// Human readable name for the router. Does not have to be unique.
Name string `json:"name" mapstructure:"name"`
// Unique identifier for the router.
ID string `json:"id" mapstructure:"id"`
// Owner of the router. Only admin users can specify a tenant identifier
// other than its own.
TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
Routes []Route `json:"routes" mapstructure:"routes"`
}
// RouterPage is the page returned by a pager when traversing over a
// collection of routers.
type RouterPage struct {
pagination.LinkedPageBase
}
// NextPageURL is invoked when a paginated collection of routers 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 RouterPage) NextPageURL() (string, error) {
type resp struct {
Links []gophercloud.Link `mapstructure:"routers_links"`
}
var r resp
err := mapstructure.Decode(p.Body, &r)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(r.Links)
}
// IsEmpty checks whether a RouterPage struct is empty.
func (p RouterPage) IsEmpty() (bool, error) {
is, err := ExtractRouters(p)
if err != nil {
return true, nil
}
return len(is) == 0, nil
}
// ExtractRouters accepts a Page struct, specifically a RouterPage struct,
// and extracts the elements into a slice of Router structs. In other words,
// a generic collection is mapped into a relevant slice.
func ExtractRouters(page pagination.Page) ([]Router, error) {
var resp struct {
Routers []Router `mapstructure:"routers" json:"routers"`
}
err := mapstructure.Decode(page.(RouterPage).Body, &resp)
return resp.Routers, err
}
type commonResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts a router.
func (r commonResult) Extract() (*Router, error) {
if r.Err != nil {
return nil, r.Err
}
var res struct {
Router *Router `json:"router"`
}
err := mapstructure.Decode(r.Body, &res)
return res.Router, err
}
// CreateResult represents the result of a create operation.
type CreateResult struct {
commonResult
}
// GetResult represents the result of a get operation.
type GetResult struct {
commonResult
}
// UpdateResult represents the result of an update operation.
type UpdateResult struct {
commonResult
}
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
gophercloud.ErrResult
}
// InterfaceInfo represents information about a particular router interface. As
// mentioned above, in order for a router to forward to a subnet, it needs an
// interface.
type InterfaceInfo struct {
// The ID of the subnet which this interface is associated with.
SubnetID string `json:"subnet_id" mapstructure:"subnet_id"`
// The ID of the port that is a part of the subnet.
PortID string `json:"port_id" mapstructure:"port_id"`
// The UUID of the interface.
ID string `json:"id" mapstructure:"id"`
// Owner of the interface.
TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
}
// InterfaceResult represents the result of interface operations, such as
// AddInterface() and RemoveInterface().
type InterfaceResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts an information struct.
func (r InterfaceResult) Extract() (*InterfaceInfo, error) {
if r.Err != nil {
return nil, r.Err
}
var res *InterfaceInfo
err := mapstructure.Decode(r.Body, &res)
return res, err
}

View File

@@ -1,21 +0,0 @@
package routers
import "github.com/rackspace/gophercloud"
const resourcePath = "routers"
func rootURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL(resourcePath)
}
func resourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(resourcePath, id)
}
func addInterfaceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(resourcePath, id, "add_router_interface")
}
func removeInterfaceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(resourcePath, id, "remove_router_interface")
}

View File

@@ -1,3 +0,0 @@
// Package lbaas provides information and interaction with the Load Balancer
// as a Service extension for the OpenStack Networking service.
package lbaas

View File

@@ -1,21 +0,0 @@
// Package provider gives access to the provider Neutron plugin, allowing
// network extended attributes. The provider extended attributes for networks
// enable administrative users to specify how network objects map to the
// underlying networking infrastructure. These extended attributes also appear
// when administrative users query networks.
//
// For more information about extended attributes, see the NetworkExtAttrs
// struct. The actual semantics of these attributes depend on the technology
// back end of the particular plug-in. See the plug-in documentation and the
// OpenStack Cloud Administrator Guide to understand which values should be
// specific for each of these attributes when OpenStack Networking is deployed
// with a particular plug-in. The examples shown in this chapter refer to the
// Open vSwitch plug-in.
//
// The default policy settings enable only users with administrative rights to
// specify these parameters in requests and to see their values in responses. By
// default, the provider network extension attributes are completely hidden from
// regular tenants. As a rule of thumb, if these attributes are not visible in a
// GET /networks/<network-id> operation, this implies the user submitting the
// request is not authorized to view or manipulate provider network attributes.
package provider

View File

@@ -1,124 +0,0 @@
package provider
import (
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
"github.com/rackspace/gophercloud/pagination"
)
// AdminState gives users a solid type to work with for create and update
// operations. It is recommended that users use the `Up` and `Down` enums.
type AdminState *bool
// Convenience vars for AdminStateUp values.
var (
iTrue = true
iFalse = false
Up AdminState = &iTrue
Down AdminState = &iFalse
)
// NetworkExtAttrs represents an extended form of a Network with additional fields.
type NetworkExtAttrs struct {
// UUID for the network
ID string `mapstructure:"id" json:"id"`
// Human-readable name for the network. Might not be unique.
Name string `mapstructure:"name" json:"name"`
// The administrative state of network. If false (down), the network does not forward packets.
AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"`
// Indicates whether network is currently operational. Possible values include
// `ACTIVE', `DOWN', `BUILD', or `ERROR'. Plug-ins might define additional values.
Status string `mapstructure:"status" json:"status"`
// Subnets associated with this network.
Subnets []string `mapstructure:"subnets" json:"subnets"`
// Owner of network. Only admin users can specify a tenant_id other than its own.
TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
// Specifies whether the network resource can be accessed by any tenant or not.
Shared bool `mapstructure:"shared" json:"shared"`
// Specifies the nature of the physical network mapped to this network
// resource. Examples are flat, vlan, or gre.
NetworkType string `json:"provider:network_type" mapstructure:"provider:network_type"`
// Identifies the physical network on top of which this network object is
// being implemented. The OpenStack Networking API does not expose any facility
// for retrieving the list of available physical networks. As an example, in
// the Open vSwitch plug-in this is a symbolic name which is then mapped to
// specific bridges on each compute host through the Open vSwitch plug-in
// configuration file.
PhysicalNetwork string `json:"provider:physical_network" mapstructure:"provider:physical_network"`
// Identifies an isolated segment on the physical network; the nature of the
// segment depends on the segmentation model defined by network_type. For
// instance, if network_type is vlan, then this is a vlan identifier;
// otherwise, if network_type is gre, then this will be a gre key.
SegmentationID string `json:"provider:segmentation_id" mapstructure:"provider:segmentation_id"`
}
// ExtractGet decorates a GetResult struct returned from a networks.Get()
// function with extended attributes.
func ExtractGet(r networks.GetResult) (*NetworkExtAttrs, error) {
if r.Err != nil {
return nil, r.Err
}
var res struct {
Network *NetworkExtAttrs `json:"network"`
}
err := mapstructure.WeakDecode(r.Body, &res)
return res.Network, err
}
// ExtractCreate decorates a CreateResult struct returned from a networks.Create()
// function with extended attributes.
func ExtractCreate(r networks.CreateResult) (*NetworkExtAttrs, error) {
if r.Err != nil {
return nil, r.Err
}
var res struct {
Network *NetworkExtAttrs `json:"network"`
}
err := mapstructure.WeakDecode(r.Body, &res)
return res.Network, err
}
// ExtractUpdate decorates a UpdateResult struct returned from a
// networks.Update() function with extended attributes.
func ExtractUpdate(r networks.UpdateResult) (*NetworkExtAttrs, error) {
if r.Err != nil {
return nil, r.Err
}
var res struct {
Network *NetworkExtAttrs `json:"network"`
}
err := mapstructure.WeakDecode(r.Body, &res)
return res.Network, err
}
// ExtractList accepts a Page struct, specifically a NetworkPage struct, and
// extracts the elements into a slice of NetworkExtAttrs structs. In other
// words, a generic collection is mapped into a relevant slice.
func ExtractList(page pagination.Page) ([]NetworkExtAttrs, error) {
var resp struct {
Networks []NetworkExtAttrs `mapstructure:"networks" json:"networks"`
}
err := mapstructure.WeakDecode(page.(networks.NetworkPage).Body, &resp)
return resp.Networks, err
}

View File

@@ -1,32 +0,0 @@
// Package security contains functionality to work with security group and
// security group rules Neutron resources.
//
// Security groups and security group rules allows administrators and tenants
// the ability to specify the type of traffic and direction (ingress/egress)
// that is allowed to pass through a port. A security group is a container for
// security group rules.
//
// When a port is created in Networking it is associated with a security group.
// If a security group is not specified the port is associated with a 'default'
// security group. By default, this group drops all ingress traffic and allows
// all egress. Rules can be added to this group in order to change the behaviour.
//
// The basic characteristics of Neutron Security Groups are:
//
// For ingress traffic (to an instance)
// - Only traffic matched with security group rules are allowed.
// - When there is no rule defined, all traffic is dropped.
//
// For egress traffic (from an instance)
// - Only traffic matched with security group rules are allowed.
// - When there is no rule defined, all egress traffic are dropped.
// - When a new security group is created, rules to allow all egress traffic
// is automatically added.
//
// "default security group" is defined for each tenant.
// - For the default security group a rule which allows intercommunication
// among hosts associated with the default security group is defined by default.
// - As a result, all egress traffic and intercommunication in the default
// group are allowed and all ingress from outside of the default group is
// dropped by default (in the default security group).
package security

View File

@@ -1,131 +0,0 @@
package groups
import (
"fmt"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// 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 floating IP 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 {
ID string `q:"id"`
Name string `q:"name"`
TenantID string `q:"tenant_id"`
Limit int `q:"limit"`
Marker string `q:"marker"`
SortKey string `q:"sort_key"`
SortDir string `q:"sort_dir"`
}
// List returns a Pager which allows you to iterate over a collection of
// security groups. 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 {
q, err := gophercloud.BuildQueryString(&opts)
if err != nil {
return pagination.Pager{Err: err}
}
u := rootURL(c) + q.String()
return pagination.NewPager(c, u, func(r pagination.PageResult) pagination.Page {
return SecGroupPage{pagination.LinkedPageBase{PageResult: r}}
})
}
var (
errNameRequired = fmt.Errorf("Name is required")
)
// CreateOpts contains all the values needed to create a new security group.
type CreateOpts struct {
// Required. Human-readable name for the VIP. Does not have to be unique.
Name string
// Required for admins. Indicates the owner of the VIP.
TenantID string
// Optional. Describes the security group.
Description string
}
// Create is an operation which provisions a new security group with default
// security group rules for the IPv4 and IPv6 ether types.
func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
var res CreateResult
// Validate required opts
if opts.Name == "" {
res.Err = errNameRequired
return res
}
type secgroup struct {
Name string `json:"name"`
TenantID string `json:"tenant_id,omitempty"`
Description string `json:"description,omitempty"`
}
type request struct {
SecGroup secgroup `json:"security_group"`
}
reqBody := request{SecGroup: secgroup{
Name: opts.Name,
TenantID: opts.TenantID,
Description: opts.Description,
}}
_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
return res
}
// Get retrieves a particular security group based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) GetResult {
var res GetResult
_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
return res
}
// Delete will permanently delete a particular security group based on its unique ID.
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
var res DeleteResult
_, res.Err = c.Delete(resourceURL(c, id), nil)
return res
}
// IDFromName is a convenience function that returns a security group's ID given its name.
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
securityGroupCount := 0
securityGroupID := ""
if name == "" {
return "", fmt.Errorf("A security group name must be provided.")
}
pager := List(client, ListOpts{})
pager.EachPage(func(page pagination.Page) (bool, error) {
securityGroupList, err := ExtractGroups(page)
if err != nil {
return false, err
}
for _, s := range securityGroupList {
if s.Name == name {
securityGroupCount++
securityGroupID = s.ID
}
}
return true, nil
})
switch securityGroupCount {
case 0:
return "", fmt.Errorf("Unable to find security group: %s", name)
case 1:
return securityGroupID, nil
default:
return "", fmt.Errorf("Found %d security groups matching %s", securityGroupCount, name)
}
}

View File

@@ -1,108 +0,0 @@
package groups
import (
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules"
"github.com/rackspace/gophercloud/pagination"
)
// SecGroup represents a container for security group rules.
type SecGroup struct {
// The UUID for the security group.
ID string
// Human-readable name for the security group. Might not be unique. Cannot be
// named "default" as that is automatically created for a tenant.
Name string
// The security group description.
Description string
// A slice of security group rules that dictate the permitted behaviour for
// traffic entering and leaving the group.
Rules []rules.SecGroupRule `json:"security_group_rules" mapstructure:"security_group_rules"`
// Owner of the security group. Only admin users can specify a TenantID
// other than their own.
TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
}
// SecGroupPage is the page returned by a pager when traversing over a
// collection of security groups.
type SecGroupPage struct {
pagination.LinkedPageBase
}
// NextPageURL is invoked when a paginated collection of security groups 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 SecGroupPage) NextPageURL() (string, error) {
type resp struct {
Links []gophercloud.Link `mapstructure:"security_groups_links"`
}
var r resp
err := mapstructure.Decode(p.Body, &r)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(r.Links)
}
// IsEmpty checks whether a SecGroupPage struct is empty.
func (p SecGroupPage) IsEmpty() (bool, error) {
is, err := ExtractGroups(p)
if err != nil {
return true, nil
}
return len(is) == 0, nil
}
// ExtractGroups accepts a Page struct, specifically a SecGroupPage struct,
// and extracts the elements into a slice of SecGroup structs. In other words,
// a generic collection is mapped into a relevant slice.
func ExtractGroups(page pagination.Page) ([]SecGroup, error) {
var resp struct {
SecGroups []SecGroup `mapstructure:"security_groups" json:"security_groups"`
}
err := mapstructure.Decode(page.(SecGroupPage).Body, &resp)
return resp.SecGroups, err
}
type commonResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts a security group.
func (r commonResult) Extract() (*SecGroup, error) {
if r.Err != nil {
return nil, r.Err
}
var res struct {
SecGroup *SecGroup `mapstructure:"security_group" json:"security_group"`
}
err := mapstructure.Decode(r.Body, &res)
return res.SecGroup, err
}
// CreateResult represents the result of a create operation.
type CreateResult struct {
commonResult
}
// GetResult represents the result of a get operation.
type GetResult struct {
commonResult
}
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
gophercloud.ErrResult
}

View File

@@ -1,13 +0,0 @@
package groups
import "github.com/rackspace/gophercloud"
const rootPath = "security-groups"
func rootURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL(rootPath)
}
func resourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(rootPath, id)
}

View File

@@ -1,174 +0,0 @@
package rules
import (
"fmt"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// 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 security group 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 {
Direction string `q:"direction"`
EtherType string `q:"ethertype"`
ID string `q:"id"`
PortRangeMax int `q:"port_range_max"`
PortRangeMin int `q:"port_range_min"`
Protocol string `q:"protocol"`
RemoteGroupID string `q:"remote_group_id"`
RemoteIPPrefix string `q:"remote_ip_prefix"`
SecGroupID string `q:"security_group_id"`
TenantID string `q:"tenant_id"`
Limit int `q:"limit"`
Marker string `q:"marker"`
SortKey string `q:"sort_key"`
SortDir string `q:"sort_dir"`
}
// List returns a Pager which allows you to iterate over a collection of
// security group rules. 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 {
q, err := gophercloud.BuildQueryString(&opts)
if err != nil {
return pagination.Pager{Err: err}
}
u := rootURL(c) + q.String()
return pagination.NewPager(c, u, func(r pagination.PageResult) pagination.Page {
return SecGroupRulePage{pagination.LinkedPageBase{PageResult: r}}
})
}
// Errors
var (
errValidDirectionRequired = fmt.Errorf("A valid Direction is required")
errValidEtherTypeRequired = fmt.Errorf("A valid EtherType is required")
errSecGroupIDRequired = fmt.Errorf("A valid SecGroupID is required")
errValidProtocolRequired = fmt.Errorf("A valid Protocol is required")
)
// Constants useful for CreateOpts
const (
DirIngress = "ingress"
DirEgress = "egress"
Ether4 = "IPv4"
Ether6 = "IPv6"
ProtocolTCP = "tcp"
ProtocolUDP = "udp"
ProtocolICMP = "icmp"
)
// CreateOpts contains all the values needed to create a new security group rule.
type CreateOpts struct {
// Required. Must be either "ingress" or "egress": the direction in which the
// security group rule is applied.
Direction string
// Required. Must be "IPv4" or "IPv6", and addresses represented in CIDR must
// match the ingress or egress rules.
EtherType string
// Required. The security group ID to associate with this security group rule.
SecGroupID string
// Optional. The maximum port number in the range that is matched by the
// security group rule. The PortRangeMin attribute constrains the PortRangeMax
// attribute. If the protocol is ICMP, this value must be an ICMP type.
PortRangeMax int
// Optional. The minimum port number in the range that is matched by the
// security group rule. If the protocol is TCP or UDP, this value must be
// less than or equal to the value of the PortRangeMax attribute. If the
// protocol is ICMP, this value must be an ICMP type.
PortRangeMin int
// Optional. The protocol that is matched by the security group rule. Valid
// values are "tcp", "udp", "icmp" or an empty string.
Protocol string
// Optional. The remote group ID to be associated with this security group
// rule. You can specify either RemoteGroupID or RemoteIPPrefix.
RemoteGroupID string
// Optional. The remote IP prefix to be associated with this security group
// rule. You can specify either RemoteGroupID or RemoteIPPrefix. This
// attribute matches the specified IP prefix as the source IP address of the
// IP packet.
RemoteIPPrefix string
// Required for admins. Indicates the owner of the VIP.
TenantID string
}
// Create is an operation which adds a new security group rule and associates it
// with an existing security group (whose ID is specified in CreateOpts).
func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
var res CreateResult
// Validate required opts
if opts.Direction != DirIngress && opts.Direction != DirEgress {
res.Err = errValidDirectionRequired
return res
}
if opts.EtherType != Ether4 && opts.EtherType != Ether6 {
res.Err = errValidEtherTypeRequired
return res
}
if opts.SecGroupID == "" {
res.Err = errSecGroupIDRequired
return res
}
if opts.Protocol != "" && opts.Protocol != ProtocolTCP && opts.Protocol != ProtocolUDP && opts.Protocol != ProtocolICMP {
res.Err = errValidProtocolRequired
return res
}
type secrule struct {
Direction string `json:"direction"`
EtherType string `json:"ethertype"`
SecGroupID string `json:"security_group_id"`
PortRangeMax int `json:"port_range_max,omitempty"`
PortRangeMin int `json:"port_range_min,omitempty"`
Protocol string `json:"protocol,omitempty"`
RemoteGroupID string `json:"remote_group_id,omitempty"`
RemoteIPPrefix string `json:"remote_ip_prefix,omitempty"`
TenantID string `json:"tenant_id,omitempty"`
}
type request struct {
SecRule secrule `json:"security_group_rule"`
}
reqBody := request{SecRule: secrule{
Direction: opts.Direction,
EtherType: opts.EtherType,
SecGroupID: opts.SecGroupID,
PortRangeMax: opts.PortRangeMax,
PortRangeMin: opts.PortRangeMin,
Protocol: opts.Protocol,
RemoteGroupID: opts.RemoteGroupID,
RemoteIPPrefix: opts.RemoteIPPrefix,
TenantID: opts.TenantID,
}}
_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
return res
}
// Get retrieves a particular security group rule based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) GetResult {
var res GetResult
_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
return res
}
// Delete will permanently delete a particular security group rule based on its unique ID.
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
var res DeleteResult
_, res.Err = c.Delete(resourceURL(c, id), nil)
return res
}

View File

@@ -1,133 +0,0 @@
package rules
import (
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// SecGroupRule represents a rule to dictate the behaviour of incoming or
// outgoing traffic for a particular security group.
type SecGroupRule struct {
// The UUID for this security group rule.
ID string
// The direction in which the security group rule is applied. The only values
// allowed are "ingress" or "egress". For a compute instance, an ingress
// security group rule is applied to incoming (ingress) traffic for that
// instance. An egress rule is applied to traffic leaving the instance.
Direction string
// Must be IPv4 or IPv6, and addresses represented in CIDR must match the
// ingress or egress rules.
EtherType string `json:"ethertype" mapstructure:"ethertype"`
// The security group ID to associate with this security group rule.
SecGroupID string `json:"security_group_id" mapstructure:"security_group_id"`
// The minimum port number in the range that is matched by the security group
// rule. If the protocol is TCP or UDP, this value must be less than or equal
// to the value of the PortRangeMax attribute. If the protocol is ICMP, this
// value must be an ICMP type.
PortRangeMin int `json:"port_range_min" mapstructure:"port_range_min"`
// The maximum port number in the range that is matched by the security group
// rule. The PortRangeMin attribute constrains the PortRangeMax attribute. If
// the protocol is ICMP, this value must be an ICMP type.
PortRangeMax int `json:"port_range_max" mapstructure:"port_range_max"`
// The protocol that is matched by the security group rule. Valid values are
// "tcp", "udp", "icmp" or an empty string.
Protocol string
// The remote group ID to be associated with this security group rule. You
// can specify either RemoteGroupID or RemoteIPPrefix.
RemoteGroupID string `json:"remote_group_id" mapstructure:"remote_group_id"`
// The remote IP prefix to be associated with this security group rule. You
// can specify either RemoteGroupID or RemoteIPPrefix . This attribute
// matches the specified IP prefix as the source IP address of the IP packet.
RemoteIPPrefix string `json:"remote_ip_prefix" mapstructure:"remote_ip_prefix"`
// The owner of this security group rule.
TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
}
// SecGroupRulePage is the page returned by a pager when traversing over a
// collection of security group rules.
type SecGroupRulePage struct {
pagination.LinkedPageBase
}
// NextPageURL is invoked when a paginated collection of security group rules 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 SecGroupRulePage) NextPageURL() (string, error) {
type resp struct {
Links []gophercloud.Link `mapstructure:"security_group_rules_links"`
}
var r resp
err := mapstructure.Decode(p.Body, &r)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(r.Links)
}
// IsEmpty checks whether a SecGroupRulePage struct is empty.
func (p SecGroupRulePage) IsEmpty() (bool, error) {
is, err := ExtractRules(p)
if err != nil {
return true, nil
}
return len(is) == 0, nil
}
// ExtractRules accepts a Page struct, specifically a SecGroupRulePage struct,
// and extracts the elements into a slice of SecGroupRule structs. In other words,
// a generic collection is mapped into a relevant slice.
func ExtractRules(page pagination.Page) ([]SecGroupRule, error) {
var resp struct {
SecGroupRules []SecGroupRule `mapstructure:"security_group_rules" json:"security_group_rules"`
}
err := mapstructure.Decode(page.(SecGroupRulePage).Body, &resp)
return resp.SecGroupRules, err
}
type commonResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts a security rule.
func (r commonResult) Extract() (*SecGroupRule, error) {
if r.Err != nil {
return nil, r.Err
}
var res struct {
SecGroupRule *SecGroupRule `mapstructure:"security_group_rule" json:"security_group_rule"`
}
err := mapstructure.Decode(r.Body, &res)
return res.SecGroupRule, err
}
// CreateResult represents the result of a create operation.
type CreateResult struct {
commonResult
}
// GetResult represents the result of a get operation.
type GetResult struct {
commonResult
}
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
gophercloud.ErrResult
}

View File

@@ -1,13 +0,0 @@
package rules
import "github.com/rackspace/gophercloud"
const rootPath = "security-group-rules"
func rootURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL(rootPath)
}
func resourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(rootPath, id)
}

View File

@@ -1,9 +0,0 @@
// 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

View File

@@ -1 +0,0 @@
package networks

View File

@@ -1,226 +0,0 @@
package networks
import (
"fmt"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// AdminState gives users a solid type to work with for create and update
// operations. It is recommended that users use the `Up` and `Down` enums.
type AdminState *bool
// Convenience vars for AdminStateUp values.
var (
iTrue = true
iFalse = false
Up AdminState = &iTrue
Down AdminState = &iFalse
)
type networkOpts struct {
AdminStateUp *bool
Name string
Shared *bool
TenantID string
}
// ListOptsBuilder allows extensions to add additional parameters to the
// List request.
type ListOptsBuilder interface {
ToNetworkListQuery() (string, error)
}
// 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 `q:"status"`
Name string `q:"name"`
AdminStateUp *bool `q:"admin_state_up"`
TenantID string `q:"tenant_id"`
Shared *bool `q:"shared"`
ID string `q:"id"`
Marker string `q:"marker"`
Limit int `q:"limit"`
SortKey string `q:"sort_key"`
SortDir string `q:"sort_dir"`
}
// ToNetworkListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToNetworkListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return "", err
}
return q.String(), nil
}
// 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 ListOptsBuilder) pagination.Pager {
url := listURL(c)
if opts != nil {
query, err := opts.ToNetworkListQuery()
if err != nil {
return pagination.Pager{Err: err}
}
url += query
}
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
return NetworkPage{pagination.LinkedPageBase{PageResult: r}}
})
}
// Get retrieves a specific network based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) GetResult {
var res GetResult
_, res.Err = c.Get(getURL(c, id), &res.Body, nil)
return res
}
// CreateOptsBuilder is the interface options structs have to satisfy in order
// to be used in the main Create operation in this package. Since many
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type CreateOptsBuilder interface {
ToNetworkCreateMap() (map[string]interface{}, error)
}
// CreateOpts is the common options struct used in this package's Create
// operation.
type CreateOpts networkOpts
// ToNetworkCreateMap casts a CreateOpts struct to a map.
func (opts CreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
n := make(map[string]interface{})
if opts.AdminStateUp != nil {
n["admin_state_up"] = &opts.AdminStateUp
}
if opts.Name != "" {
n["name"] = opts.Name
}
if opts.Shared != nil {
n["shared"] = &opts.Shared
}
if opts.TenantID != "" {
n["tenant_id"] = opts.TenantID
}
return map[string]interface{}{"network": n}, nil
}
// 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 CreateOptsBuilder) CreateResult {
var res CreateResult
reqBody, err := opts.ToNetworkCreateMap()
if err != nil {
res.Err = err
return res
}
_, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil)
return res
}
// UpdateOptsBuilder is the interface options structs have to satisfy in order
// to be used in the main Update operation in this package. Since many
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type UpdateOptsBuilder interface {
ToNetworkUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts is the common options struct used in this package's Update
// operation.
type UpdateOpts networkOpts
// ToNetworkUpdateMap casts a UpdateOpts struct to a map.
func (opts UpdateOpts) ToNetworkUpdateMap() (map[string]interface{}, error) {
n := make(map[string]interface{})
if opts.AdminStateUp != nil {
n["admin_state_up"] = &opts.AdminStateUp
}
if opts.Name != "" {
n["name"] = opts.Name
}
if opts.Shared != nil {
n["shared"] = &opts.Shared
}
return map[string]interface{}{"network": n}, nil
}
// 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 UpdateOptsBuilder) UpdateResult {
var res UpdateResult
reqBody, err := opts.ToNetworkUpdateMap()
if err != nil {
res.Err = err
return res
}
// Send request to API
_, res.Err = c.Put(updateURL(c, networkID), reqBody, &res.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 201},
})
return res
}
// Delete accepts a unique ID and deletes the network associated with it.
func Delete(c *gophercloud.ServiceClient, networkID string) DeleteResult {
var res DeleteResult
_, res.Err = c.Delete(deleteURL(c, networkID), nil)
return res
}
// IDFromName is a convenience function that returns a network's ID given its name.
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
networkCount := 0
networkID := ""
if name == "" {
return "", fmt.Errorf("A network name must be provided.")
}
pager := List(client, nil)
pager.EachPage(func(page pagination.Page) (bool, error) {
networkList, err := ExtractNetworks(page)
if err != nil {
return false, err
}
for _, n := range networkList {
if n.Name == name {
networkCount++
networkID = n.ID
}
}
return true, nil
})
switch networkCount {
case 0:
return "", fmt.Errorf("Unable to find network: %s", name)
case 1:
return networkID, nil
default:
return "", fmt.Errorf("Found %d networks matching %s", networkCount, name)
}
}

View File

@@ -1,116 +0,0 @@
package networks
import (
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
type commonResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts a network resource.
func (r commonResult) Extract() (*Network, error) {
if r.Err != nil {
return nil, r.Err
}
var res struct {
Network *Network `json:"network"`
}
err := mapstructure.Decode(r.Body, &res)
return res.Network, err
}
// CreateResult represents the result of a create operation.
type CreateResult struct {
commonResult
}
// GetResult represents the result of a get operation.
type GetResult struct {
commonResult
}
// UpdateResult represents the result of an update operation.
type UpdateResult struct {
commonResult
}
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
gophercloud.ErrResult
}
// Network represents, well, a network.
type Network struct {
// UUID for the network
ID string `mapstructure:"id" json:"id"`
// Human-readable name for the network. Might not be unique.
Name string `mapstructure:"name" json:"name"`
// The administrative state of network. If false (down), the network does not forward packets.
AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"`
// Indicates whether network is currently operational. Possible values include
// `ACTIVE', `DOWN', `BUILD', or `ERROR'. Plug-ins might define additional values.
Status string `mapstructure:"status" json:"status"`
// Subnets associated with this network.
Subnets []string `mapstructure:"subnets" json:"subnets"`
// Owner of network. Only admin users can specify a tenant_id other than its own.
TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
// Specifies whether the network resource can be accessed by any tenant or not.
Shared bool `mapstructure:"shared" json:"shared"`
}
// NetworkPage is the page returned by a pager when traversing over a
// collection of networks.
type NetworkPage struct {
pagination.LinkedPageBase
}
// 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 resp struct {
Links []gophercloud.Link `mapstructure:"networks_links"`
}
var r resp
err := mapstructure.Decode(p.Body, &r)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(r.Links)
}
// 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"`
}
err := mapstructure.Decode(page.(NetworkPage).Body, &resp)
return resp.Networks, err
}

View File

@@ -1,31 +0,0 @@
package networks
import "github.com/rackspace/gophercloud"
func resourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL("networks", id)
}
func rootURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("networks")
}
func getURL(c *gophercloud.ServiceClient, id string) string {
return resourceURL(c, id)
}
func listURL(c *gophercloud.ServiceClient) string {
return rootURL(c)
}
func createURL(c *gophercloud.ServiceClient) string {
return rootURL(c)
}
func updateURL(c *gophercloud.ServiceClient, id string) string {
return resourceURL(c, id)
}
func deleteURL(c *gophercloud.ServiceClient, id string) string {
return resourceURL(c, id)
}

View File

@@ -1,8 +0,0 @@
// Package ports contains functionality for working with Neutron port resources.
// A port represents a virtual switch port on a logical network switch. Virtual
// instances attach their interfaces into ports. The logical port also defines
// the MAC address and the IP address(es) to be assigned to the interfaces
// plugged into them. When IP addresses are associated to a port, this also
// implies the port is associated with a subnet, as the IP address was taken
// from the allocation pool for a specific subnet.
package ports

View File

@@ -1,11 +0,0 @@
package ports
import "fmt"
func err(str string) error {
return fmt.Errorf("%s", str)
}
var (
errNetworkIDRequired = err("A Network ID is required")
)

View File

@@ -1,268 +0,0 @@
package ports
import (
"fmt"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// AdminState gives users a solid type to work with for create and update
// operations. It is recommended that users use the `Up` and `Down` enums.
type AdminState *bool
// Convenience vars for AdminStateUp values.
var (
iTrue = true
iFalse = false
Up AdminState = &iTrue
Down AdminState = &iFalse
)
// ListOptsBuilder allows extensions to add additional parameters to the
// List request.
type ListOptsBuilder interface {
ToPortListQuery() (string, error)
}
// 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 port attributes you want to see returned. SortKey allows you to sort
// by a particular port attribute. SortDir sets the direction, and is either
// `asc' or `desc'. Marker and Limit are used for pagination.
type ListOpts struct {
Status string `q:"status"`
Name string `q:"name"`
AdminStateUp *bool `q:"admin_state_up"`
NetworkID string `q:"network_id"`
TenantID string `q:"tenant_id"`
DeviceOwner string `q:"device_owner"`
MACAddress string `q:"mac_address"`
ID string `q:"id"`
DeviceID string `q:"device_id"`
Limit int `q:"limit"`
Marker string `q:"marker"`
SortKey string `q:"sort_key"`
SortDir string `q:"sort_dir"`
}
// ToPortListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToPortListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return "", err
}
return q.String(), nil
}
// List returns a Pager which allows you to iterate over a collection of
// ports. It accepts a ListOpts struct, which allows you to filter and sort
// the returned collection for greater efficiency.
//
// Default policy settings return only those ports that are owned by the tenant
// who submits the request, unless the request is submitted by a user with
// administrative rights.
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
url := listURL(c)
if opts != nil {
query, err := opts.ToPortListQuery()
if err != nil {
return pagination.Pager{Err: err}
}
url += query
}
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
return PortPage{pagination.LinkedPageBase{PageResult: r}}
})
}
// Get retrieves a specific port based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) GetResult {
var res GetResult
_, res.Err = c.Get(getURL(c, id), &res.Body, nil)
return res
}
// CreateOptsBuilder is the interface options structs have to satisfy in order
// to be used in the main Create operation in this package. Since many
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type CreateOptsBuilder interface {
ToPortCreateMap() (map[string]interface{}, error)
}
// CreateOpts represents the attributes used when creating a new port.
type CreateOpts struct {
NetworkID string
Name string
AdminStateUp *bool
MACAddress string
FixedIPs interface{}
DeviceID string
DeviceOwner string
TenantID string
SecurityGroups []string
AllowedAddressPairs []AddressPair
}
// ToPortCreateMap casts a CreateOpts struct to a map.
func (opts CreateOpts) ToPortCreateMap() (map[string]interface{}, error) {
p := make(map[string]interface{})
if opts.NetworkID == "" {
return nil, errNetworkIDRequired
}
p["network_id"] = opts.NetworkID
if opts.DeviceID != "" {
p["device_id"] = opts.DeviceID
}
if opts.DeviceOwner != "" {
p["device_owner"] = opts.DeviceOwner
}
if opts.FixedIPs != nil {
p["fixed_ips"] = opts.FixedIPs
}
if opts.SecurityGroups != nil {
p["security_groups"] = opts.SecurityGroups
}
if opts.TenantID != "" {
p["tenant_id"] = opts.TenantID
}
if opts.AdminStateUp != nil {
p["admin_state_up"] = &opts.AdminStateUp
}
if opts.Name != "" {
p["name"] = opts.Name
}
if opts.MACAddress != "" {
p["mac_address"] = opts.MACAddress
}
if opts.AllowedAddressPairs != nil {
p["allowed_address_pairs"] = opts.AllowedAddressPairs
}
return map[string]interface{}{"port": p}, nil
}
// Create accepts a CreateOpts struct and creates a new network using the values
// provided. You must remember to provide a NetworkID value.
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
var res CreateResult
reqBody, err := opts.ToPortCreateMap()
if err != nil {
res.Err = err
return res
}
_, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil)
return res
}
// UpdateOptsBuilder is the interface options structs have to satisfy in order
// to be used in the main Update operation in this package. Since many
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type UpdateOptsBuilder interface {
ToPortUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts represents the attributes used when updating an existing port.
type UpdateOpts struct {
Name string
AdminStateUp *bool
FixedIPs interface{}
DeviceID string
DeviceOwner string
SecurityGroups []string
AllowedAddressPairs []AddressPair
}
// ToPortUpdateMap casts an UpdateOpts struct to a map.
func (opts UpdateOpts) ToPortUpdateMap() (map[string]interface{}, error) {
p := make(map[string]interface{})
if opts.DeviceID != "" {
p["device_id"] = opts.DeviceID
}
if opts.DeviceOwner != "" {
p["device_owner"] = opts.DeviceOwner
}
if opts.FixedIPs != nil {
p["fixed_ips"] = opts.FixedIPs
}
if opts.SecurityGroups != nil {
p["security_groups"] = opts.SecurityGroups
}
if opts.AdminStateUp != nil {
p["admin_state_up"] = &opts.AdminStateUp
}
if opts.Name != "" {
p["name"] = opts.Name
}
if opts.AllowedAddressPairs != nil {
p["allowed_address_pairs"] = opts.AllowedAddressPairs
}
return map[string]interface{}{"port": p}, nil
}
// Update accepts a UpdateOpts struct and updates an existing port using the
// values provided.
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
var res UpdateResult
reqBody, err := opts.ToPortUpdateMap()
if err != nil {
res.Err = err
return res
}
_, res.Err = c.Put(updateURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 201},
})
return res
}
// Delete accepts a unique ID and deletes the port associated with it.
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
var res DeleteResult
_, res.Err = c.Delete(deleteURL(c, id), nil)
return res
}
// IDFromName is a convenience function that returns a port's ID given its name.
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
portCount := 0
portID := ""
if name == "" {
return "", fmt.Errorf("A port name must be provided.")
}
pager := List(client, nil)
pager.EachPage(func(page pagination.Page) (bool, error) {
portList, err := ExtractPorts(page)
if err != nil {
return false, err
}
for _, p := range portList {
if p.Name == name {
portCount++
portID = p.ID
}
}
return true, nil
})
switch portCount {
case 0:
return "", fmt.Errorf("Unable to find port: %s", name)
case 1:
return portID, nil
default:
return "", fmt.Errorf("Found %d ports matching %s", portCount, name)
}
}

View File

@@ -1,132 +0,0 @@
package ports
import (
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
type commonResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts a port resource.
func (r commonResult) Extract() (*Port, error) {
if r.Err != nil {
return nil, r.Err
}
var res struct {
Port *Port `json:"port"`
}
err := mapstructure.Decode(r.Body, &res)
return res.Port, err
}
// CreateResult represents the result of a create operation.
type CreateResult struct {
commonResult
}
// GetResult represents the result of a get operation.
type GetResult struct {
commonResult
}
// UpdateResult represents the result of an update operation.
type UpdateResult struct {
commonResult
}
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
gophercloud.ErrResult
}
// IP is a sub-struct that represents an individual IP.
type IP struct {
SubnetID string `mapstructure:"subnet_id" json:"subnet_id"`
IPAddress string `mapstructure:"ip_address" json:"ip_address,omitempty"`
}
type AddressPair struct {
IPAddress string `mapstructure:"ip_address" json:"ip_address,omitempty"`
MACAddress string `mapstructure:"mac_address" json:"mac_address,omitempty"`
}
// Port represents a Neutron port. See package documentation for a top-level
// description of what this is.
type Port struct {
// UUID for the port.
ID string `mapstructure:"id" json:"id"`
// Network that this port is associated with.
NetworkID string `mapstructure:"network_id" json:"network_id"`
// Human-readable name for the port. Might not be unique.
Name string `mapstructure:"name" json:"name"`
// Administrative state of port. If false (down), port does not forward packets.
AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"`
// Indicates whether network is currently operational. Possible values include
// `ACTIVE', `DOWN', `BUILD', or `ERROR'. Plug-ins might define additional values.
Status string `mapstructure:"status" json:"status"`
// Mac address to use on this port.
MACAddress string `mapstructure:"mac_address" json:"mac_address"`
// Specifies IP addresses for the port thus associating the port itself with
// the subnets where the IP addresses are picked from
FixedIPs []IP `mapstructure:"fixed_ips" json:"fixed_ips"`
// Owner of network. Only admin users can specify a tenant_id other than its own.
TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
// Identifies the entity (e.g.: dhcp agent) using this port.
DeviceOwner string `mapstructure:"device_owner" json:"device_owner"`
// Specifies the IDs of any security groups associated with a port.
SecurityGroups []string `mapstructure:"security_groups" json:"security_groups"`
// Identifies the device (e.g., virtual server) using this port.
DeviceID string `mapstructure:"device_id" json:"device_id"`
// Identifies the list of IP addresses the port will recognize/accept
AllowedAddressPairs []AddressPair `mapstructure:"allowed_address_pairs" json:"allowed_address_pairs"`
}
// PortPage is the page returned by a pager when traversing over a collection
// of network ports.
type PortPage struct {
pagination.LinkedPageBase
}
// NextPageURL is invoked when a paginated collection of ports 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 PortPage) NextPageURL() (string, error) {
type resp struct {
Links []gophercloud.Link `mapstructure:"ports_links"`
}
var r resp
err := mapstructure.Decode(p.Body, &r)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(r.Links)
}
// IsEmpty checks whether a PortPage struct is empty.
func (p PortPage) IsEmpty() (bool, error) {
is, err := ExtractPorts(p)
if err != nil {
return true, nil
}
return len(is) == 0, nil
}
// ExtractPorts accepts a Page struct, specifically a PortPage struct,
// and extracts the elements into a slice of Port structs. In other words,
// a generic collection is mapped into a relevant slice.
func ExtractPorts(page pagination.Page) ([]Port, error) {
var resp struct {
Ports []Port `mapstructure:"ports" json:"ports"`
}
err := mapstructure.Decode(page.(PortPage).Body, &resp)
return resp.Ports, err
}

View File

@@ -1,31 +0,0 @@
package ports
import "github.com/rackspace/gophercloud"
func resourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL("ports", id)
}
func rootURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("ports")
}
func listURL(c *gophercloud.ServiceClient) string {
return rootURL(c)
}
func getURL(c *gophercloud.ServiceClient, id string) string {
return resourceURL(c, id)
}
func createURL(c *gophercloud.ServiceClient) string {
return rootURL(c)
}
func updateURL(c *gophercloud.ServiceClient, id string) string {
return resourceURL(c, id)
}
func deleteURL(c *gophercloud.ServiceClient, id string) string {
return resourceURL(c, id)
}

View File

@@ -1,10 +0,0 @@
// Package subnets contains functionality for working with Neutron subnet
// resources. A subnet represents an IP address block that can be used to
// assign IP addresses to virtual instances. Each subnet must have a CIDR and
// must be associated with a network. IPs can either be selected from the whole
// subnet CIDR or from allocation pools specified by the user.
//
// A subnet can also have a gateway, a list of DNS name servers, and host routes.
// This information is pushed to instances whose interfaces are associated with
// the subnet.
package subnets

View File

@@ -1,13 +0,0 @@
package subnets
import "fmt"
func err(str string) error {
return fmt.Errorf("%s", str)
}
var (
errNetworkIDRequired = err("A network ID is required")
errCIDRRequired = err("A valid CIDR is required")
errInvalidIPType = err("An IP type must either be 4 or 6")
)

View File

@@ -1,271 +0,0 @@
package subnets
import (
"fmt"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// AdminState gives users a solid type to work with for create and update
// operations. It is recommended that users use the `Up` and `Down` enums.
type AdminState *bool
// Convenience vars for AdminStateUp values.
var (
iTrue = true
iFalse = false
Up AdminState = &iTrue
Down AdminState = &iFalse
)
// ListOptsBuilder allows extensions to add additional parameters to the
// List request.
type ListOptsBuilder interface {
ToSubnetListQuery() (string, error)
}
// 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 subnet attributes you want to see returned. SortKey allows you to sort
// by a particular subnet attribute. SortDir sets the direction, and is either
// `asc' or `desc'. Marker and Limit are used for pagination.
type ListOpts struct {
Name string `q:"name"`
EnableDHCP *bool `q:"enable_dhcp"`
NetworkID string `q:"network_id"`
TenantID string `q:"tenant_id"`
IPVersion int `q:"ip_version"`
GatewayIP string `q:"gateway_ip"`
CIDR string `q:"cidr"`
ID string `q:"id"`
Limit int `q:"limit"`
Marker string `q:"marker"`
SortKey string `q:"sort_key"`
SortDir string `q:"sort_dir"`
}
// ToSubnetListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToSubnetListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return "", err
}
return q.String(), nil
}
// List returns a Pager which allows you to iterate over a collection of
// subnets. It accepts a ListOpts struct, which allows you to filter and sort
// the returned collection for greater efficiency.
//
// Default policy settings return only those subnets that are owned by the tenant
// who submits the request, unless the request is submitted by a user with
// administrative rights.
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
url := listURL(c)
if opts != nil {
query, err := opts.ToSubnetListQuery()
if err != nil {
return pagination.Pager{Err: err}
}
url += query
}
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
return SubnetPage{pagination.LinkedPageBase{PageResult: r}}
})
}
// Get retrieves a specific subnet based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) GetResult {
var res GetResult
_, res.Err = c.Get(getURL(c, id), &res.Body, nil)
return res
}
// Valid IP types
const (
IPv4 = 4
IPv6 = 6
)
// CreateOptsBuilder is the interface options structs have to satisfy in order
// to be used in the main Create operation in this package. Since many
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type CreateOptsBuilder interface {
ToSubnetCreateMap() (map[string]interface{}, error)
}
// CreateOpts represents the attributes used when creating a new subnet.
type CreateOpts struct {
// Required
NetworkID string
CIDR string
// Optional
Name string
TenantID string
AllocationPools []AllocationPool
GatewayIP string
IPVersion int
EnableDHCP *bool
DNSNameservers []string
HostRoutes []HostRoute
}
// ToSubnetCreateMap casts a CreateOpts struct to a map.
func (opts CreateOpts) ToSubnetCreateMap() (map[string]interface{}, error) {
s := make(map[string]interface{})
if opts.NetworkID == "" {
return nil, errNetworkIDRequired
}
if opts.CIDR == "" {
return nil, errCIDRRequired
}
if opts.IPVersion != 0 && opts.IPVersion != IPv4 && opts.IPVersion != IPv6 {
return nil, errInvalidIPType
}
s["network_id"] = opts.NetworkID
s["cidr"] = opts.CIDR
if opts.EnableDHCP != nil {
s["enable_dhcp"] = &opts.EnableDHCP
}
if opts.Name != "" {
s["name"] = opts.Name
}
if opts.GatewayIP != "" {
s["gateway_ip"] = opts.GatewayIP
}
if opts.TenantID != "" {
s["tenant_id"] = opts.TenantID
}
if opts.IPVersion != 0 {
s["ip_version"] = opts.IPVersion
}
if len(opts.AllocationPools) != 0 {
s["allocation_pools"] = opts.AllocationPools
}
if len(opts.DNSNameservers) != 0 {
s["dns_nameservers"] = opts.DNSNameservers
}
if len(opts.HostRoutes) != 0 {
s["host_routes"] = opts.HostRoutes
}
return map[string]interface{}{"subnet": s}, nil
}
// Create accepts a CreateOpts struct and creates a new subnet using the values
// provided. You must remember to provide a valid NetworkID, CIDR and IP version.
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
var res CreateResult
reqBody, err := opts.ToSubnetCreateMap()
if err != nil {
res.Err = err
return res
}
_, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil)
return res
}
// UpdateOptsBuilder allows extensions to add additional parameters to the
// Update request.
type UpdateOptsBuilder interface {
ToSubnetUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts represents the attributes used when updating an existing subnet.
type UpdateOpts struct {
Name string
GatewayIP string
DNSNameservers []string
HostRoutes []HostRoute
EnableDHCP *bool
}
// ToSubnetUpdateMap casts an UpdateOpts struct to a map.
func (opts UpdateOpts) ToSubnetUpdateMap() (map[string]interface{}, error) {
s := make(map[string]interface{})
if opts.EnableDHCP != nil {
s["enable_dhcp"] = &opts.EnableDHCP
}
if opts.Name != "" {
s["name"] = opts.Name
}
if opts.GatewayIP != "" {
s["gateway_ip"] = opts.GatewayIP
}
if opts.DNSNameservers != nil {
s["dns_nameservers"] = opts.DNSNameservers
}
if opts.HostRoutes != nil {
s["host_routes"] = opts.HostRoutes
}
return map[string]interface{}{"subnet": s}, nil
}
// Update accepts a UpdateOpts struct and updates an existing subnet using the
// values provided.
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
var res UpdateResult
reqBody, err := opts.ToSubnetUpdateMap()
if err != nil {
res.Err = err
return res
}
_, res.Err = c.Put(updateURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 201},
})
return res
}
// Delete accepts a unique ID and deletes the subnet associated with it.
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
var res DeleteResult
_, res.Err = c.Delete(deleteURL(c, id), nil)
return res
}
// IDFromName is a convenience function that returns a subnet's ID given its name.
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
subnetCount := 0
subnetID := ""
if name == "" {
return "", fmt.Errorf("A subnet name must be provided.")
}
pager := List(client, nil)
pager.EachPage(func(page pagination.Page) (bool, error) {
subnetList, err := ExtractSubnets(page)
if err != nil {
return false, err
}
for _, s := range subnetList {
if s.Name == name {
subnetCount++
subnetID = s.ID
}
}
return true, nil
})
switch subnetCount {
case 0:
return "", fmt.Errorf("Unable to find subnet: %s", name)
case 1:
return subnetID, nil
default:
return "", fmt.Errorf("Found %d subnets matching %s", subnetCount, name)
}
}

View File

@@ -1,132 +0,0 @@
package subnets
import (
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
type commonResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts a subnet resource.
func (r commonResult) Extract() (*Subnet, error) {
if r.Err != nil {
return nil, r.Err
}
var res struct {
Subnet *Subnet `json:"subnet"`
}
err := mapstructure.Decode(r.Body, &res)
return res.Subnet, err
}
// CreateResult represents the result of a create operation.
type CreateResult struct {
commonResult
}
// GetResult represents the result of a get operation.
type GetResult struct {
commonResult
}
// UpdateResult represents the result of an update operation.
type UpdateResult struct {
commonResult
}
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
gophercloud.ErrResult
}
// AllocationPool represents a sub-range of cidr available for dynamic
// allocation to ports, e.g. {Start: "10.0.0.2", End: "10.0.0.254"}
type AllocationPool struct {
Start string `json:"start"`
End string `json:"end"`
}
// HostRoute represents a route that should be used by devices with IPs from
// a subnet (not including local subnet route).
type HostRoute struct {
DestinationCIDR string `mapstructure:"destination" json:"destination"`
NextHop string `mapstructure:"nexthop" json:"nexthop"`
}
// Subnet represents a subnet. See package documentation for a top-level
// description of what this is.
type Subnet struct {
// UUID representing the subnet
ID string `mapstructure:"id" json:"id"`
// UUID of the parent network
NetworkID string `mapstructure:"network_id" json:"network_id"`
// Human-readable name for the subnet. Might not be unique.
Name string `mapstructure:"name" json:"name"`
// IP version, either `4' or `6'
IPVersion int `mapstructure:"ip_version" json:"ip_version"`
// CIDR representing IP range for this subnet, based on IP version
CIDR string `mapstructure:"cidr" json:"cidr"`
// Default gateway used by devices in this subnet
GatewayIP string `mapstructure:"gateway_ip" json:"gateway_ip"`
// DNS name servers used by hosts in this subnet.
DNSNameservers []string `mapstructure:"dns_nameservers" json:"dns_nameservers"`
// Sub-ranges of CIDR available for dynamic allocation to ports. See AllocationPool.
AllocationPools []AllocationPool `mapstructure:"allocation_pools" json:"allocation_pools"`
// Routes that should be used by devices with IPs from this subnet (not including local subnet route).
HostRoutes []HostRoute `mapstructure:"host_routes" json:"host_routes"`
// Specifies whether DHCP is enabled for this subnet or not.
EnableDHCP bool `mapstructure:"enable_dhcp" json:"enable_dhcp"`
// Owner of network. Only admin users can specify a tenant_id other than its own.
TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
}
// SubnetPage is the page returned by a pager when traversing over a collection
// of subnets.
type SubnetPage struct {
pagination.LinkedPageBase
}
// NextPageURL is invoked when a paginated collection of subnets 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 SubnetPage) NextPageURL() (string, error) {
type resp struct {
Links []gophercloud.Link `mapstructure:"subnets_links"`
}
var r resp
err := mapstructure.Decode(p.Body, &r)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(r.Links)
}
// IsEmpty checks whether a SubnetPage struct is empty.
func (p SubnetPage) IsEmpty() (bool, error) {
is, err := ExtractSubnets(p)
if err != nil {
return true, nil
}
return len(is) == 0, nil
}
// ExtractSubnets accepts a Page struct, specifically a SubnetPage struct,
// and extracts the elements into a slice of Subnet structs. In other words,
// a generic collection is mapped into a relevant slice.
func ExtractSubnets(page pagination.Page) ([]Subnet, error) {
var resp struct {
Subnets []Subnet `mapstructure:"subnets" json:"subnets"`
}
err := mapstructure.Decode(page.(SubnetPage).Body, &resp)
return resp.Subnets, err
}

View File

@@ -1,31 +0,0 @@
package subnets
import "github.com/rackspace/gophercloud"
func resourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL("subnets", id)
}
func rootURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("subnets")
}
func listURL(c *gophercloud.ServiceClient) string {
return rootURL(c)
}
func getURL(c *gophercloud.ServiceClient, id string) string {
return resourceURL(c, id)
}
func createURL(c *gophercloud.ServiceClient) string {
return rootURL(c)
}
func updateURL(c *gophercloud.ServiceClient, id string) string {
return resourceURL(c, id)
}
func deleteURL(c *gophercloud.ServiceClient, id string) string {
return resourceURL(c, id)
}