Move to vendor
As we walk away from 1.4, godep no longer requires to have stuff into workspace and we no longer need the symlink. Signed-off-by: Olivier Gambier <olivier@docker.com>
This commit is contained in:
106
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/requests.go
generated
vendored
Normal file
106
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/requests.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
package bootfromvolume
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
)
|
||||
|
||||
// SourceType represents the type of medium being used to create the volume.
|
||||
type SourceType string
|
||||
|
||||
const (
|
||||
Volume SourceType = "volume"
|
||||
Snapshot SourceType = "snapshot"
|
||||
Image SourceType = "image"
|
||||
)
|
||||
|
||||
// BlockDevice is a structure with options for booting a server instance
|
||||
// from a volume. The volume may be created from an image, snapshot, or another
|
||||
// volume.
|
||||
type BlockDevice struct {
|
||||
// BootIndex [optional] is the boot index. It defaults to 0.
|
||||
BootIndex int `json:"boot_index"`
|
||||
|
||||
// DeleteOnTermination [optional] specifies whether or not to delete the attached volume
|
||||
// when the server is deleted. Defaults to `false`.
|
||||
DeleteOnTermination bool `json:"delete_on_termination"`
|
||||
|
||||
// DestinationType [optional] is the type that gets created. Possible values are "volume"
|
||||
// and "local".
|
||||
DestinationType string `json:"destination_type"`
|
||||
|
||||
// SourceType [required] must be one of: "volume", "snapshot", "image".
|
||||
SourceType SourceType `json:"source_type"`
|
||||
|
||||
// UUID [required] is the unique identifier for the volume, snapshot, or image (see above)
|
||||
UUID string `json:"uuid"`
|
||||
|
||||
// VolumeSize [optional] is the size of the volume to create (in gigabytes).
|
||||
VolumeSize int `json:"volume_size"`
|
||||
}
|
||||
|
||||
// CreateOptsExt is a structure that extends the server `CreateOpts` structure
|
||||
// by allowing for a block device mapping.
|
||||
type CreateOptsExt struct {
|
||||
servers.CreateOptsBuilder
|
||||
BlockDevice []BlockDevice `json:"block_device_mapping_v2,omitempty"`
|
||||
}
|
||||
|
||||
// ToServerCreateMap adds the block device mapping option to the base server
|
||||
// creation options.
|
||||
func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
|
||||
base, err := opts.CreateOptsBuilder.ToServerCreateMap()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(opts.BlockDevice) == 0 {
|
||||
return nil, errors.New("Required fields UUID and SourceType not set.")
|
||||
}
|
||||
|
||||
serverMap := base["server"].(map[string]interface{})
|
||||
|
||||
blockDevice := make([]map[string]interface{}, len(opts.BlockDevice))
|
||||
|
||||
for i, bd := range opts.BlockDevice {
|
||||
if string(bd.SourceType) == "" {
|
||||
return nil, errors.New("SourceType must be one of: volume, image, snapshot.")
|
||||
}
|
||||
|
||||
blockDevice[i] = make(map[string]interface{})
|
||||
|
||||
blockDevice[i]["source_type"] = bd.SourceType
|
||||
blockDevice[i]["boot_index"] = strconv.Itoa(bd.BootIndex)
|
||||
blockDevice[i]["delete_on_termination"] = strconv.FormatBool(bd.DeleteOnTermination)
|
||||
blockDevice[i]["volume_size"] = strconv.Itoa(bd.VolumeSize)
|
||||
if bd.UUID != "" {
|
||||
blockDevice[i]["uuid"] = bd.UUID
|
||||
}
|
||||
if bd.DestinationType != "" {
|
||||
blockDevice[i]["destination_type"] = bd.DestinationType
|
||||
}
|
||||
|
||||
}
|
||||
serverMap["block_device_mapping_v2"] = blockDevice
|
||||
|
||||
return base, nil
|
||||
}
|
||||
|
||||
// Create requests the creation of a server from the given block device mapping.
|
||||
func Create(client *gophercloud.ServiceClient, opts servers.CreateOptsBuilder) servers.CreateResult {
|
||||
var res servers.CreateResult
|
||||
|
||||
reqBody, err := opts.ToServerCreateMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
_, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200, 202},
|
||||
})
|
||||
return res
|
||||
}
|
||||
51
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/requests_test.go
generated
vendored
Normal file
51
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/requests_test.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
package bootfromvolume
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestCreateOpts(t *testing.T) {
|
||||
base := servers.CreateOpts{
|
||||
Name: "createdserver",
|
||||
ImageRef: "asdfasdfasdf",
|
||||
FlavorRef: "performance1-1",
|
||||
}
|
||||
|
||||
ext := CreateOptsExt{
|
||||
CreateOptsBuilder: base,
|
||||
BlockDevice: []BlockDevice{
|
||||
BlockDevice{
|
||||
UUID: "123456",
|
||||
SourceType: Image,
|
||||
DestinationType: "volume",
|
||||
VolumeSize: 10,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := `
|
||||
{
|
||||
"server": {
|
||||
"name": "createdserver",
|
||||
"imageRef": "asdfasdfasdf",
|
||||
"flavorRef": "performance1-1",
|
||||
"block_device_mapping_v2":[
|
||||
{
|
||||
"uuid":"123456",
|
||||
"source_type":"image",
|
||||
"destination_type":"volume",
|
||||
"boot_index": "0",
|
||||
"delete_on_termination": "false",
|
||||
"volume_size": "10"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`
|
||||
actual, err := ext.ToServerCreateMap()
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckJSONEquals(t, expected, actual)
|
||||
}
|
||||
10
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/results.go
generated
vendored
Normal file
10
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/results.go
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
package bootfromvolume
|
||||
|
||||
import (
|
||||
os "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
)
|
||||
|
||||
// CreateResult temporarily contains the response from a Create call.
|
||||
type CreateResult struct {
|
||||
os.CreateResult
|
||||
}
|
||||
7
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/urls.go
generated
vendored
Normal file
7
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/urls.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
package bootfromvolume
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
func createURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL("os-volumes_boot")
|
||||
}
|
||||
16
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/urls_test.go
generated
vendored
Normal file
16
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume/urls_test.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
package bootfromvolume
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
func TestCreateURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"os-volumes_boot", createURL(c))
|
||||
}
|
||||
1
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/doc.go
generated
vendored
Normal file
1
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/doc.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package defsecrules
|
||||
108
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/fixtures.go
generated
vendored
Normal file
108
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
package defsecrules
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
const rootPath = "/os-security-group-default-rules"
|
||||
|
||||
func mockListRulesResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"security_group_default_rules": [
|
||||
{
|
||||
"from_port": 80,
|
||||
"id": "{ruleID}",
|
||||
"ip_protocol": "TCP",
|
||||
"ip_range": {
|
||||
"cidr": "10.10.10.0/24"
|
||||
},
|
||||
"to_port": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func mockCreateRuleResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"security_group_default_rule": {
|
||||
"ip_protocol": "TCP",
|
||||
"from_port": 80,
|
||||
"to_port": 80,
|
||||
"cidr": "10.10.12.0/24"
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"security_group_default_rule": {
|
||||
"from_port": 80,
|
||||
"id": "{ruleID}",
|
||||
"ip_protocol": "TCP",
|
||||
"ip_range": {
|
||||
"cidr": "10.10.12.0/24"
|
||||
},
|
||||
"to_port": 80
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func mockGetRuleResponse(t *testing.T, ruleID string) {
|
||||
url := rootPath + "/" + ruleID
|
||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"security_group_default_rule": {
|
||||
"id": "{ruleID}",
|
||||
"from_port": 80,
|
||||
"to_port": 80,
|
||||
"ip_protocol": "TCP",
|
||||
"ip_range": {
|
||||
"cidr": "10.10.12.0/24"
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func mockDeleteRuleResponse(t *testing.T, ruleID string) {
|
||||
url := rootPath + "/" + ruleID
|
||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "DELETE")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
}
|
||||
95
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/requests.go
generated
vendored
Normal file
95
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/requests.go
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
package defsecrules
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// List will return a collection of default rules.
|
||||
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
||||
createPage := func(r pagination.PageResult) pagination.Page {
|
||||
return DefaultRulePage{pagination.SinglePageBase(r)}
|
||||
}
|
||||
|
||||
return pagination.NewPager(client, rootURL(client), createPage)
|
||||
}
|
||||
|
||||
// CreateOpts represents the configuration for adding a new default rule.
|
||||
type CreateOpts struct {
|
||||
// Required - the lower bound of the port range that will be opened.
|
||||
FromPort int `json:"from_port"`
|
||||
|
||||
// Required - the upper bound of the port range that will be opened.
|
||||
ToPort int `json:"to_port"`
|
||||
|
||||
// Required - the protocol type that will be allowed, e.g. TCP.
|
||||
IPProtocol string `json:"ip_protocol"`
|
||||
|
||||
// ONLY required if FromGroupID is blank. This represents the IP range that
|
||||
// will be the source of network traffic to your security group. Use
|
||||
// 0.0.0.0/0 to allow all IP addresses.
|
||||
CIDR string `json:"cidr,omitempty"`
|
||||
}
|
||||
|
||||
// CreateOptsBuilder builds the create rule options into a serializable format.
|
||||
type CreateOptsBuilder interface {
|
||||
ToRuleCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// ToRuleCreateMap builds the create rule options into a serializable format.
|
||||
func (opts CreateOpts) ToRuleCreateMap() (map[string]interface{}, error) {
|
||||
rule := make(map[string]interface{})
|
||||
|
||||
if opts.FromPort == 0 {
|
||||
return rule, errors.New("A FromPort must be set")
|
||||
}
|
||||
if opts.ToPort == 0 {
|
||||
return rule, errors.New("A ToPort must be set")
|
||||
}
|
||||
if opts.IPProtocol == "" {
|
||||
return rule, errors.New("A IPProtocol must be set")
|
||||
}
|
||||
if opts.CIDR == "" {
|
||||
return rule, errors.New("A CIDR must be set")
|
||||
}
|
||||
|
||||
rule["from_port"] = opts.FromPort
|
||||
rule["to_port"] = opts.ToPort
|
||||
rule["ip_protocol"] = opts.IPProtocol
|
||||
rule["cidr"] = opts.CIDR
|
||||
|
||||
return map[string]interface{}{"security_group_default_rule": rule}, nil
|
||||
}
|
||||
|
||||
// Create is the operation responsible for creating a new default rule.
|
||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
||||
var result CreateResult
|
||||
|
||||
reqBody, err := opts.ToRuleCreateMap()
|
||||
if err != nil {
|
||||
result.Err = err
|
||||
return result
|
||||
}
|
||||
|
||||
_, result.Err = client.Post(rootURL(client), reqBody, &result.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Get will return details for a particular default rule.
|
||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||
var result GetResult
|
||||
_, result.Err = client.Get(resourceURL(client, id), &result.Body, nil)
|
||||
return result
|
||||
}
|
||||
|
||||
// Delete will permanently delete a default rule from the project.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
||||
var result gophercloud.ErrResult
|
||||
_, result.Err = client.Delete(resourceURL(client, id), nil)
|
||||
return result
|
||||
}
|
||||
100
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/requests_test.go
generated
vendored
Normal file
100
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/requests_test.go
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
package defsecrules
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
const ruleID = "{ruleID}"
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
mockListRulesResponse(t)
|
||||
|
||||
count := 0
|
||||
|
||||
err := List(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
|
||||
count++
|
||||
actual, err := ExtractDefaultRules(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
expected := []DefaultRule{
|
||||
DefaultRule{
|
||||
FromPort: 80,
|
||||
ID: ruleID,
|
||||
IPProtocol: "TCP",
|
||||
IPRange: secgroups.IPRange{CIDR: "10.10.10.0/24"},
|
||||
ToPort: 80,
|
||||
},
|
||||
}
|
||||
|
||||
th.CheckDeepEquals(t, expected, actual)
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
th.AssertEquals(t, 1, count)
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
mockCreateRuleResponse(t)
|
||||
|
||||
opts := CreateOpts{
|
||||
IPProtocol: "TCP",
|
||||
FromPort: 80,
|
||||
ToPort: 80,
|
||||
CIDR: "10.10.12.0/24",
|
||||
}
|
||||
|
||||
group, err := Create(client.ServiceClient(), opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
expected := &DefaultRule{
|
||||
ID: ruleID,
|
||||
FromPort: 80,
|
||||
ToPort: 80,
|
||||
IPProtocol: "TCP",
|
||||
IPRange: secgroups.IPRange{CIDR: "10.10.12.0/24"},
|
||||
}
|
||||
th.AssertDeepEquals(t, expected, group)
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
mockGetRuleResponse(t, ruleID)
|
||||
|
||||
group, err := Get(client.ServiceClient(), ruleID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
expected := &DefaultRule{
|
||||
ID: ruleID,
|
||||
FromPort: 80,
|
||||
ToPort: 80,
|
||||
IPProtocol: "TCP",
|
||||
IPRange: secgroups.IPRange{CIDR: "10.10.12.0/24"},
|
||||
}
|
||||
|
||||
th.AssertDeepEquals(t, expected, group)
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
mockDeleteRuleResponse(t, ruleID)
|
||||
|
||||
err := Delete(client.ServiceClient(), ruleID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
69
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/results.go
generated
vendored
Normal file
69
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/results.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
package defsecrules
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// DefaultRule represents a default rule - which is identical to a
|
||||
// normal security rule.
|
||||
type DefaultRule secgroups.Rule
|
||||
|
||||
// DefaultRulePage is a single page of a DefaultRule collection.
|
||||
type DefaultRulePage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
|
||||
// IsEmpty determines whether or not a page of default rules contains any results.
|
||||
func (page DefaultRulePage) IsEmpty() (bool, error) {
|
||||
users, err := ExtractDefaultRules(page)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return len(users) == 0, nil
|
||||
}
|
||||
|
||||
// ExtractDefaultRules returns a slice of DefaultRules contained in a single
|
||||
// page of results.
|
||||
func ExtractDefaultRules(page pagination.Page) ([]DefaultRule, error) {
|
||||
casted := page.(DefaultRulePage).Body
|
||||
var response struct {
|
||||
Rules []DefaultRule `mapstructure:"security_group_default_rules"`
|
||||
}
|
||||
|
||||
err := mapstructure.WeakDecode(casted, &response)
|
||||
|
||||
return response.Rules, err
|
||||
}
|
||||
|
||||
type commonResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// CreateResult represents the result of a create operation.
|
||||
type CreateResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// GetResult represents the result of a get operation.
|
||||
type GetResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// Extract will extract a DefaultRule struct from most responses.
|
||||
func (r commonResult) Extract() (*DefaultRule, error) {
|
||||
if r.Err != nil {
|
||||
return nil, r.Err
|
||||
}
|
||||
|
||||
var response struct {
|
||||
Rule DefaultRule `mapstructure:"security_group_default_rule"`
|
||||
}
|
||||
|
||||
err := mapstructure.WeakDecode(r.Body, &response)
|
||||
|
||||
return &response.Rule, err
|
||||
}
|
||||
13
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/urls.go
generated
vendored
Normal file
13
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules/urls.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
package defsecrules
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
const rulepath = "os-security-group-default-rules"
|
||||
|
||||
func resourceURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return c.ServiceURL(rulepath, id)
|
||||
}
|
||||
|
||||
func rootURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL(rulepath)
|
||||
}
|
||||
23
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/delegate.go
generated
vendored
Normal file
23
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/delegate.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
package extensions
|
||||
|
||||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
common "github.com/rackspace/gophercloud/openstack/common/extensions"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// ExtractExtensions interprets a Page as a slice of Extensions.
|
||||
func ExtractExtensions(page pagination.Page) ([]common.Extension, error) {
|
||||
return common.ExtractExtensions(page)
|
||||
}
|
||||
|
||||
// Get retrieves information for a specific extension using its alias.
|
||||
func Get(c *gophercloud.ServiceClient, alias string) common.GetResult {
|
||||
return 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)
|
||||
}
|
||||
96
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/delegate_test.go
generated
vendored
Normal file
96
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/delegate_test.go
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
package extensions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
common "github.com/rackspace/gophercloud/openstack/common/extensions"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
th.Mux.HandleFunc("/extensions", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"extensions": [
|
||||
{
|
||||
"updated": "2013-01-20T00:00:00-00:00",
|
||||
"name": "Neutron Service Type Management",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/ext/neutron/service-type/api/v1.0",
|
||||
"alias": "service-type",
|
||||
"description": "API for retrieving service providers for Neutron advanced services"
|
||||
}
|
||||
]
|
||||
}
|
||||
`)
|
||||
})
|
||||
|
||||
count := 0
|
||||
List(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
|
||||
count++
|
||||
actual, err := ExtractExtensions(page)
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
expected := []common.Extension{
|
||||
common.Extension{
|
||||
Updated: "2013-01-20T00:00:00-00:00",
|
||||
Name: "Neutron Service Type Management",
|
||||
Links: []interface{}{},
|
||||
Namespace: "http://docs.openstack.org/ext/neutron/service-type/api/v1.0",
|
||||
Alias: "service-type",
|
||||
Description: "API for retrieving service providers for Neutron advanced services",
|
||||
},
|
||||
}
|
||||
th.AssertDeepEquals(t, expected, actual)
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.CheckEquals(t, 1, count)
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
th.Mux.HandleFunc("/extensions/agent", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"extension": {
|
||||
"updated": "2013-02-03T10:00:00-00:00",
|
||||
"name": "agent",
|
||||
"links": [],
|
||||
"namespace": "http://docs.openstack.org/ext/agent/api/v2.0",
|
||||
"alias": "agent",
|
||||
"description": "The agent management extension."
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
|
||||
ext, err := Get(client.ServiceClient(), "agent").Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
th.AssertEquals(t, ext.Updated, "2013-02-03T10:00:00-00:00")
|
||||
th.AssertEquals(t, ext.Name, "agent")
|
||||
th.AssertEquals(t, ext.Namespace, "http://docs.openstack.org/ext/agent/api/v2.0")
|
||||
th.AssertEquals(t, ext.Alias, "agent")
|
||||
th.AssertEquals(t, ext.Description, "The agent management extension.")
|
||||
}
|
||||
3
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/doc.go
generated
vendored
Normal file
3
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/doc.go
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
// Package diskconfig provides information and interaction with the Disk
|
||||
// Config extension that works with the OpenStack Compute service.
|
||||
package diskconfig
|
||||
114
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/requests.go
generated
vendored
Normal file
114
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/requests.go
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
package diskconfig
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
)
|
||||
|
||||
// DiskConfig represents one of the two possible settings for the DiskConfig option when creating,
|
||||
// rebuilding, or resizing servers: Auto or Manual.
|
||||
type DiskConfig string
|
||||
|
||||
const (
|
||||
// Auto builds a server with a single partition the size of the target flavor disk and
|
||||
// automatically adjusts the filesystem to fit the entire partition. Auto may only be used with
|
||||
// images and servers that use a single EXT3 partition.
|
||||
Auto DiskConfig = "AUTO"
|
||||
|
||||
// Manual builds a server using whatever partition scheme and filesystem are present in the source
|
||||
// image. If the target flavor disk is larger, the remaining space is left unpartitioned. This
|
||||
// enables images to have non-EXT3 filesystems, multiple partitions, and so on, and enables you
|
||||
// to manage the disk configuration. It also results in slightly shorter boot times.
|
||||
Manual DiskConfig = "MANUAL"
|
||||
)
|
||||
|
||||
// ErrInvalidDiskConfig is returned if an invalid string is specified for a DiskConfig option.
|
||||
var ErrInvalidDiskConfig = errors.New("DiskConfig must be either diskconfig.Auto or diskconfig.Manual.")
|
||||
|
||||
// Validate ensures that a DiskConfig contains an appropriate value.
|
||||
func (config DiskConfig) validate() error {
|
||||
switch config {
|
||||
case Auto, Manual:
|
||||
return nil
|
||||
default:
|
||||
return ErrInvalidDiskConfig
|
||||
}
|
||||
}
|
||||
|
||||
// CreateOptsExt adds a DiskConfig option to the base CreateOpts.
|
||||
type CreateOptsExt struct {
|
||||
servers.CreateOptsBuilder
|
||||
|
||||
// DiskConfig [optional] controls how the created server's disk is partitioned.
|
||||
DiskConfig DiskConfig `json:"OS-DCF:diskConfig,omitempty"`
|
||||
}
|
||||
|
||||
// ToServerCreateMap adds the diskconfig option to the base server creation options.
|
||||
func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
|
||||
base, err := opts.CreateOptsBuilder.ToServerCreateMap()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if string(opts.DiskConfig) == "" {
|
||||
return base, nil
|
||||
}
|
||||
|
||||
serverMap := base["server"].(map[string]interface{})
|
||||
serverMap["OS-DCF:diskConfig"] = string(opts.DiskConfig)
|
||||
|
||||
return base, nil
|
||||
}
|
||||
|
||||
// RebuildOptsExt adds a DiskConfig option to the base RebuildOpts.
|
||||
type RebuildOptsExt struct {
|
||||
servers.RebuildOptsBuilder
|
||||
|
||||
// DiskConfig [optional] controls how the rebuilt server's disk is partitioned.
|
||||
DiskConfig DiskConfig
|
||||
}
|
||||
|
||||
// ToServerRebuildMap adds the diskconfig option to the base server rebuild options.
|
||||
func (opts RebuildOptsExt) ToServerRebuildMap() (map[string]interface{}, error) {
|
||||
err := opts.DiskConfig.validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
base, err := opts.RebuildOptsBuilder.ToServerRebuildMap()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serverMap := base["rebuild"].(map[string]interface{})
|
||||
serverMap["OS-DCF:diskConfig"] = string(opts.DiskConfig)
|
||||
|
||||
return base, nil
|
||||
}
|
||||
|
||||
// ResizeOptsExt adds a DiskConfig option to the base server resize options.
|
||||
type ResizeOptsExt struct {
|
||||
servers.ResizeOptsBuilder
|
||||
|
||||
// DiskConfig [optional] controls how the resized server's disk is partitioned.
|
||||
DiskConfig DiskConfig
|
||||
}
|
||||
|
||||
// ToServerResizeMap adds the diskconfig option to the base server creation options.
|
||||
func (opts ResizeOptsExt) ToServerResizeMap() (map[string]interface{}, error) {
|
||||
err := opts.DiskConfig.validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
base, err := opts.ResizeOptsBuilder.ToServerResizeMap()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serverMap := base["resize"].(map[string]interface{})
|
||||
serverMap["OS-DCF:diskConfig"] = string(opts.DiskConfig)
|
||||
|
||||
return base, nil
|
||||
}
|
||||
87
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/requests_test.go
generated
vendored
Normal file
87
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/requests_test.go
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
package diskconfig
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
)
|
||||
|
||||
func TestCreateOpts(t *testing.T) {
|
||||
base := servers.CreateOpts{
|
||||
Name: "createdserver",
|
||||
ImageRef: "asdfasdfasdf",
|
||||
FlavorRef: "performance1-1",
|
||||
}
|
||||
|
||||
ext := CreateOptsExt{
|
||||
CreateOptsBuilder: base,
|
||||
DiskConfig: Manual,
|
||||
}
|
||||
|
||||
expected := `
|
||||
{
|
||||
"server": {
|
||||
"name": "createdserver",
|
||||
"imageRef": "asdfasdfasdf",
|
||||
"flavorRef": "performance1-1",
|
||||
"OS-DCF:diskConfig": "MANUAL"
|
||||
}
|
||||
}
|
||||
`
|
||||
actual, err := ext.ToServerCreateMap()
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckJSONEquals(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestRebuildOpts(t *testing.T) {
|
||||
base := servers.RebuildOpts{
|
||||
Name: "rebuiltserver",
|
||||
AdminPass: "swordfish",
|
||||
ImageID: "asdfasdfasdf",
|
||||
}
|
||||
|
||||
ext := RebuildOptsExt{
|
||||
RebuildOptsBuilder: base,
|
||||
DiskConfig: Auto,
|
||||
}
|
||||
|
||||
actual, err := ext.ToServerRebuildMap()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
expected := `
|
||||
{
|
||||
"rebuild": {
|
||||
"name": "rebuiltserver",
|
||||
"imageRef": "asdfasdfasdf",
|
||||
"adminPass": "swordfish",
|
||||
"OS-DCF:diskConfig": "AUTO"
|
||||
}
|
||||
}
|
||||
`
|
||||
th.CheckJSONEquals(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestResizeOpts(t *testing.T) {
|
||||
base := servers.ResizeOpts{
|
||||
FlavorRef: "performance1-8",
|
||||
}
|
||||
|
||||
ext := ResizeOptsExt{
|
||||
ResizeOptsBuilder: base,
|
||||
DiskConfig: Auto,
|
||||
}
|
||||
|
||||
actual, err := ext.ToServerResizeMap()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
expected := `
|
||||
{
|
||||
"resize": {
|
||||
"flavorRef": "performance1-8",
|
||||
"OS-DCF:diskConfig": "AUTO"
|
||||
}
|
||||
}
|
||||
`
|
||||
th.CheckJSONEquals(t, expected, actual)
|
||||
}
|
||||
60
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/results.go
generated
vendored
Normal file
60
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/results.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
package diskconfig
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
func commonExtract(result gophercloud.Result) (*DiskConfig, error) {
|
||||
var resp struct {
|
||||
Server struct {
|
||||
DiskConfig string `mapstructure:"OS-DCF:diskConfig"`
|
||||
} `mapstructure:"server"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(result.Body, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config := DiskConfig(resp.Server.DiskConfig)
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// ExtractGet returns the disk configuration from a servers.Get call.
|
||||
func ExtractGet(result servers.GetResult) (*DiskConfig, error) {
|
||||
return commonExtract(result.Result)
|
||||
}
|
||||
|
||||
// ExtractUpdate returns the disk configuration from a servers.Update call.
|
||||
func ExtractUpdate(result servers.UpdateResult) (*DiskConfig, error) {
|
||||
return commonExtract(result.Result)
|
||||
}
|
||||
|
||||
// ExtractRebuild returns the disk configuration from a servers.Rebuild call.
|
||||
func ExtractRebuild(result servers.RebuildResult) (*DiskConfig, error) {
|
||||
return commonExtract(result.Result)
|
||||
}
|
||||
|
||||
// ExtractDiskConfig returns the DiskConfig setting for a specific server acquired from an
|
||||
// servers.ExtractServers call, while iterating through a Pager.
|
||||
func ExtractDiskConfig(page pagination.Page, index int) (*DiskConfig, error) {
|
||||
casted := page.(servers.ServerPage).Body
|
||||
|
||||
type server struct {
|
||||
DiskConfig string `mapstructure:"OS-DCF:diskConfig"`
|
||||
}
|
||||
var response struct {
|
||||
Servers []server `mapstructure:"servers"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(casted, &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config := DiskConfig(response.Servers[index].DiskConfig)
|
||||
return &config, nil
|
||||
}
|
||||
68
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/results_test.go
generated
vendored
Normal file
68
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig/results_test.go
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
package diskconfig
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
func TestExtractGet(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
servers.HandleServerGetSuccessfully(t)
|
||||
|
||||
config, err := ExtractGet(servers.Get(client.ServiceClient(), "1234asdf"))
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckEquals(t, Manual, *config)
|
||||
}
|
||||
|
||||
func TestExtractUpdate(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
servers.HandleServerUpdateSuccessfully(t)
|
||||
|
||||
r := servers.Update(client.ServiceClient(), "1234asdf", servers.UpdateOpts{
|
||||
Name: "new-name",
|
||||
})
|
||||
config, err := ExtractUpdate(r)
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckEquals(t, Manual, *config)
|
||||
}
|
||||
|
||||
func TestExtractRebuild(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
servers.HandleRebuildSuccessfully(t, servers.SingleServerBody)
|
||||
|
||||
r := servers.Rebuild(client.ServiceClient(), "1234asdf", servers.RebuildOpts{
|
||||
Name: "new-name",
|
||||
AdminPass: "swordfish",
|
||||
ImageID: "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
|
||||
AccessIPv4: "1.2.3.4",
|
||||
})
|
||||
config, err := ExtractRebuild(r)
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckEquals(t, Manual, *config)
|
||||
}
|
||||
|
||||
func TestExtractList(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
servers.HandleServerListSuccessfully(t)
|
||||
|
||||
pages := 0
|
||||
err := servers.List(client.ServiceClient(), nil).EachPage(func(page pagination.Page) (bool, error) {
|
||||
pages++
|
||||
|
||||
config, err := ExtractDiskConfig(page, 0)
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckEquals(t, Manual, *config)
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckEquals(t, pages, 1)
|
||||
}
|
||||
3
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/doc.go
generated
vendored
Normal file
3
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/doc.go
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
// Package extensions provides information and interaction with the
|
||||
// different extensions available for the OpenStack Compute service.
|
||||
package extensions
|
||||
3
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/doc.go
generated
vendored
Normal file
3
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/doc.go
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
// Package floatingip provides the ability to manage floating ips through
|
||||
// nova-network
|
||||
package floatingip
|
||||
174
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/fixtures.go
generated
vendored
Normal file
174
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
// +build fixtures
|
||||
|
||||
package floatingip
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
// ListOutput is a sample response to a List call.
|
||||
const ListOutput = `
|
||||
{
|
||||
"floating_ips": [
|
||||
{
|
||||
"fixed_ip": null,
|
||||
"id": 1,
|
||||
"instance_id": null,
|
||||
"ip": "10.10.10.1",
|
||||
"pool": "nova"
|
||||
},
|
||||
{
|
||||
"fixed_ip": "166.78.185.201",
|
||||
"id": 2,
|
||||
"instance_id": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||
"ip": "10.10.10.2",
|
||||
"pool": "nova"
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
// GetOutput is a sample response to a Get call.
|
||||
const GetOutput = `
|
||||
{
|
||||
"floating_ip": {
|
||||
"fixed_ip": "166.78.185.201",
|
||||
"id": 2,
|
||||
"instance_id": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||
"ip": "10.10.10.2",
|
||||
"pool": "nova"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
// CreateOutput is a sample response to a Post call
|
||||
const CreateOutput = `
|
||||
{
|
||||
"floating_ip": {
|
||||
"fixed_ip": null,
|
||||
"id": 1,
|
||||
"instance_id": null,
|
||||
"ip": "10.10.10.1",
|
||||
"pool": "nova"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
// FirstFloatingIP is the first result in ListOutput.
|
||||
var FirstFloatingIP = FloatingIP{
|
||||
ID: "1",
|
||||
IP: "10.10.10.1",
|
||||
Pool: "nova",
|
||||
}
|
||||
|
||||
// SecondFloatingIP is the first result in ListOutput.
|
||||
var SecondFloatingIP = FloatingIP{
|
||||
FixedIP: "166.78.185.201",
|
||||
ID: "2",
|
||||
InstanceID: "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||
IP: "10.10.10.2",
|
||||
Pool: "nova",
|
||||
}
|
||||
|
||||
// ExpectedFloatingIPsSlice is the slice of results that should be parsed
|
||||
// from ListOutput, in the expected order.
|
||||
var ExpectedFloatingIPsSlice = []FloatingIP{FirstFloatingIP, SecondFloatingIP}
|
||||
|
||||
// CreatedFloatingIP is the parsed result from CreateOutput.
|
||||
var CreatedFloatingIP = FloatingIP{
|
||||
ID: "1",
|
||||
IP: "10.10.10.1",
|
||||
Pool: "nova",
|
||||
}
|
||||
|
||||
// HandleListSuccessfully configures the test server to respond to a List request.
|
||||
func HandleListSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/os-floating-ips", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprintf(w, ListOutput)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleGetSuccessfully configures the test server to respond to a Get request
|
||||
// for an existing floating ip
|
||||
func HandleGetSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/os-floating-ips/2", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprintf(w, GetOutput)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleCreateSuccessfully configures the test server to respond to a Create request
|
||||
// for a new floating ip
|
||||
func HandleCreateSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/os-floating-ips", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"pool": "nova"
|
||||
}
|
||||
`)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprintf(w, CreateOutput)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleDeleteSuccessfully configures the test server to respond to a Delete request for a
|
||||
// an existing floating ip
|
||||
func HandleDeleteSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/os-floating-ips/1", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "DELETE")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleAssociateSuccessfully configures the test server to respond to a Post request
|
||||
// to associate an allocated floating IP
|
||||
func HandleAssociateSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/action", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"addFloatingIp": {
|
||||
"address": "10.10.10.2"
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleDisassociateSuccessfully configures the test server to respond to a Post request
|
||||
// to disassociate an allocated floating IP
|
||||
func HandleDisassociateSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/action", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"removeFloatingIp": {
|
||||
"address": "10.10.10.2"
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
})
|
||||
}
|
||||
92
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/requests.go
generated
vendored
Normal file
92
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/requests.go
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
package floatingip
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// List returns a Pager that allows you to iterate over a collection of FloatingIPs.
|
||||
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
||||
return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page {
|
||||
return FloatingIPsPage{pagination.SinglePageBase(r)}
|
||||
})
|
||||
}
|
||||
|
||||
// CreateOptsBuilder describes struct types that can be accepted by the Create call. Notable, the
|
||||
// CreateOpts struct in this package does.
|
||||
type CreateOptsBuilder interface {
|
||||
ToFloatingIPCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// CreateOpts specifies a Floating IP allocation request
|
||||
type CreateOpts struct {
|
||||
// Pool is the pool of floating IPs to allocate one from
|
||||
Pool string
|
||||
}
|
||||
|
||||
// ToFloatingIPCreateMap constructs a request body from CreateOpts.
|
||||
func (opts CreateOpts) ToFloatingIPCreateMap() (map[string]interface{}, error) {
|
||||
if opts.Pool == "" {
|
||||
return nil, errors.New("Missing field required for floating IP creation: Pool")
|
||||
}
|
||||
|
||||
return map[string]interface{}{"pool": opts.Pool}, nil
|
||||
}
|
||||
|
||||
// Create requests the creation of a new floating IP
|
||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
||||
var res CreateResult
|
||||
|
||||
reqBody, err := opts.ToFloatingIPCreateMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
_, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
// Get returns data about a previously created FloatingIP.
|
||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||
var res GetResult
|
||||
_, res.Err = client.Get(getURL(client, id), &res.Body, nil)
|
||||
return res
|
||||
}
|
||||
|
||||
// Delete requests the deletion of a previous allocated FloatingIP.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
|
||||
var res DeleteResult
|
||||
_, res.Err = client.Delete(deleteURL(client, id), nil)
|
||||
return res
|
||||
}
|
||||
|
||||
// association / disassociation
|
||||
|
||||
// Associate pairs an allocated floating IP with an instance
|
||||
func Associate(client *gophercloud.ServiceClient, serverId, fip string) AssociateResult {
|
||||
var res AssociateResult
|
||||
|
||||
addFloatingIp := make(map[string]interface{})
|
||||
addFloatingIp["address"] = fip
|
||||
reqBody := map[string]interface{}{"addFloatingIp": addFloatingIp}
|
||||
|
||||
_, res.Err = client.Post(associateURL(client, serverId), reqBody, nil, nil)
|
||||
return res
|
||||
}
|
||||
|
||||
// Disassociate decouples an allocated floating IP from an instance
|
||||
func Disassociate(client *gophercloud.ServiceClient, serverId, fip string) DisassociateResult {
|
||||
var res DisassociateResult
|
||||
|
||||
removeFloatingIp := make(map[string]interface{})
|
||||
removeFloatingIp["address"] = fip
|
||||
reqBody := map[string]interface{}{"removeFloatingIp": removeFloatingIp}
|
||||
|
||||
_, res.Err = client.Post(disassociateURL(client, serverId), reqBody, nil, nil)
|
||||
return res
|
||||
}
|
||||
80
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/requests_test.go
generated
vendored
Normal file
80
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/requests_test.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
package floatingip
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleListSuccessfully(t)
|
||||
|
||||
count := 0
|
||||
err := List(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
|
||||
count++
|
||||
actual, err := ExtractFloatingIPs(page)
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckDeepEquals(t, ExpectedFloatingIPsSlice, actual)
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckEquals(t, 1, count)
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleCreateSuccessfully(t)
|
||||
|
||||
actual, err := Create(client.ServiceClient(), CreateOpts{
|
||||
Pool: "nova",
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckDeepEquals(t, &CreatedFloatingIP, actual)
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleGetSuccessfully(t)
|
||||
|
||||
actual, err := Get(client.ServiceClient(), "2").Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckDeepEquals(t, &SecondFloatingIP, actual)
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleDeleteSuccessfully(t)
|
||||
|
||||
err := Delete(client.ServiceClient(), "1").ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func TestAssociate(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleAssociateSuccessfully(t)
|
||||
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||
fip := "10.10.10.2"
|
||||
|
||||
err := Associate(client.ServiceClient(), serverId, fip).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func TestDisassociate(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleDisassociateSuccessfully(t)
|
||||
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||
fip := "10.10.10.2"
|
||||
|
||||
err := Disassociate(client.ServiceClient(), serverId, fip).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
99
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/results.go
generated
vendored
Normal file
99
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/results.go
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
package floatingip
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// A FloatingIP is an IP that can be associated with an instance
|
||||
type FloatingIP struct {
|
||||
// ID is a unique ID of the Floating IP
|
||||
ID string `mapstructure:"id"`
|
||||
|
||||
// FixedIP is the IP of the instance related to the Floating IP
|
||||
FixedIP string `mapstructure:"fixed_ip,omitempty"`
|
||||
|
||||
// InstanceID is the ID of the instance that is using the Floating IP
|
||||
InstanceID string `mapstructure:"instance_id"`
|
||||
|
||||
// IP is the actual Floating IP
|
||||
IP string `mapstructure:"ip"`
|
||||
|
||||
// Pool is the pool of floating IPs that this floating IP belongs to
|
||||
Pool string `mapstructure:"pool"`
|
||||
}
|
||||
|
||||
// FloatingIPsPage stores a single, only page of FloatingIPs
|
||||
// results from a List call.
|
||||
type FloatingIPsPage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
|
||||
// IsEmpty determines whether or not a FloatingIPsPage is empty.
|
||||
func (page FloatingIPsPage) IsEmpty() (bool, error) {
|
||||
va, err := ExtractFloatingIPs(page)
|
||||
return len(va) == 0, err
|
||||
}
|
||||
|
||||
// ExtractFloatingIPs interprets a page of results as a slice of
|
||||
// FloatingIPs.
|
||||
func ExtractFloatingIPs(page pagination.Page) ([]FloatingIP, error) {
|
||||
casted := page.(FloatingIPsPage).Body
|
||||
var response struct {
|
||||
FloatingIPs []FloatingIP `mapstructure:"floating_ips"`
|
||||
}
|
||||
|
||||
err := mapstructure.WeakDecode(casted, &response)
|
||||
|
||||
return response.FloatingIPs, err
|
||||
}
|
||||
|
||||
type FloatingIPResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract is a method that attempts to interpret any FloatingIP resource
|
||||
// response as a FloatingIP struct.
|
||||
func (r FloatingIPResult) Extract() (*FloatingIP, error) {
|
||||
if r.Err != nil {
|
||||
return nil, r.Err
|
||||
}
|
||||
|
||||
var res struct {
|
||||
FloatingIP *FloatingIP `json:"floating_ip" mapstructure:"floating_ip"`
|
||||
}
|
||||
|
||||
err := mapstructure.WeakDecode(r.Body, &res)
|
||||
return res.FloatingIP, err
|
||||
}
|
||||
|
||||
// CreateResult is the response from a Create operation. Call its Extract method to interpret it
|
||||
// as a FloatingIP.
|
||||
type CreateResult struct {
|
||||
FloatingIPResult
|
||||
}
|
||||
|
||||
// GetResult is the response from a Get operation. Call its Extract method to interpret it
|
||||
// as a FloatingIP.
|
||||
type GetResult struct {
|
||||
FloatingIPResult
|
||||
}
|
||||
|
||||
// DeleteResult is the response from a Delete operation. Call its Extract method to determine if
|
||||
// the call succeeded or failed.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// AssociateResult is the response from a Delete operation. Call its Extract method to determine if
|
||||
// the call succeeded or failed.
|
||||
type AssociateResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// DisassociateResult is the response from a Delete operation. Call its Extract method to determine if
|
||||
// the call succeeded or failed.
|
||||
type DisassociateResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
37
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/urls.go
generated
vendored
Normal file
37
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/urls.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
package floatingip
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
const resourcePath = "os-floating-ips"
|
||||
|
||||
func resourceURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL(resourcePath)
|
||||
}
|
||||
|
||||
func listURL(c *gophercloud.ServiceClient) string {
|
||||
return resourceURL(c)
|
||||
}
|
||||
|
||||
func createURL(c *gophercloud.ServiceClient) string {
|
||||
return resourceURL(c)
|
||||
}
|
||||
|
||||
func getURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return c.ServiceURL(resourcePath, id)
|
||||
}
|
||||
|
||||
func deleteURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return getURL(c, id)
|
||||
}
|
||||
|
||||
func serverURL(c *gophercloud.ServiceClient, serverId string) string {
|
||||
return c.ServiceURL("servers/" + serverId + "/action")
|
||||
}
|
||||
|
||||
func associateURL(c *gophercloud.ServiceClient, serverId string) string {
|
||||
return serverURL(c, serverId)
|
||||
}
|
||||
|
||||
func disassociateURL(c *gophercloud.ServiceClient, serverId string) string {
|
||||
return serverURL(c, serverId)
|
||||
}
|
||||
60
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/urls_test.go
generated
vendored
Normal file
60
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip/urls_test.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
package floatingip
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
func TestListURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"os-floating-ips", listURL(c))
|
||||
}
|
||||
|
||||
func TestCreateURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"os-floating-ips", createURL(c))
|
||||
}
|
||||
|
||||
func TestGetURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
id := "1"
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"os-floating-ips/"+id, getURL(c, id))
|
||||
}
|
||||
|
||||
func TestDeleteURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
id := "1"
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"os-floating-ips/"+id, deleteURL(c, id))
|
||||
}
|
||||
|
||||
func TestAssociateURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"servers/"+serverId+"/action", associateURL(c, serverId))
|
||||
}
|
||||
|
||||
func TestDisassociateURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"servers/"+serverId+"/action", disassociateURL(c, serverId))
|
||||
}
|
||||
3
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/doc.go
generated
vendored
Normal file
3
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/doc.go
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
// Package keypairs provides information and interaction with the Keypairs
|
||||
// extension for the OpenStack Compute service.
|
||||
package keypairs
|
||||
171
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/fixtures.go
generated
vendored
Normal file
171
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
// +build fixtures
|
||||
|
||||
package keypairs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
// ListOutput is a sample response to a List call.
|
||||
const ListOutput = `
|
||||
{
|
||||
"keypairs": [
|
||||
{
|
||||
"keypair": {
|
||||
"fingerprint": "15:b0:f8:b3:f9:48:63:71:cf:7b:5b:38:6d:44:2d:4a",
|
||||
"name": "firstkey",
|
||||
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC+Eo/RZRngaGTkFs7I62ZjsIlO79KklKbMXi8F+KITD4bVQHHn+kV+4gRgkgCRbdoDqoGfpaDFs877DYX9n4z6FrAIZ4PES8TNKhatifpn9NdQYWA+IkU8CuvlEKGuFpKRi/k7JLos/gHi2hy7QUwgtRvcefvD/vgQZOVw/mGR9Q== Generated by Nova\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"keypair": {
|
||||
"fingerprint": "35:9d:d0:c3:4a:80:d3:d8:86:f1:ca:f7:df:c4:f9:d8",
|
||||
"name": "secondkey",
|
||||
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7DUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5Q== Generated by Nova\n"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
// GetOutput is a sample response to a Get call.
|
||||
const GetOutput = `
|
||||
{
|
||||
"keypair": {
|
||||
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC+Eo/RZRngaGTkFs7I62ZjsIlO79KklKbMXi8F+KITD4bVQHHn+kV+4gRgkgCRbdoDqoGfpaDFs877DYX9n4z6FrAIZ4PES8TNKhatifpn9NdQYWA+IkU8CuvlEKGuFpKRi/k7JLos/gHi2hy7QUwgtRvcefvD/vgQZOVw/mGR9Q== Generated by Nova\n",
|
||||
"name": "firstkey",
|
||||
"fingerprint": "15:b0:f8:b3:f9:48:63:71:cf:7b:5b:38:6d:44:2d:4a"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
// CreateOutput is a sample response to a Create call.
|
||||
const CreateOutput = `
|
||||
{
|
||||
"keypair": {
|
||||
"fingerprint": "35:9d:d0:c3:4a:80:d3:d8:86:f1:ca:f7:df:c4:f9:d8",
|
||||
"name": "createdkey",
|
||||
"private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7\nDUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ\n9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5QIDAQAB\nAoGAE5XO1mDhORy9COvsg+kYPUhB1GsCYxh+v88wG7HeFDKBY6KUc/Kxo6yoGn5T\nTjRjekyi2KoDZHz4VlIzyZPwFS4I1bf3oCunVoAKzgLdmnTtvRNMC5jFOGc2vUgP\n9bSyRj3S1R4ClVk2g0IDeagko/jc8zzLEYuIK+fbkds79YECQQDt3vcevgegnkga\ntF4NsDmmBPRkcSHCqrANP/7vFcBQN3czxeYYWX3DK07alu6GhH1Y4sHbdm616uU0\nll7xbDzxAkEAzAtN2IyftNygV2EGiaGgqLyo/tD9+Vui2qCQplqe4jvWh/5Sparl\nOjmKo+uAW+hLrLVMnHzRWxbWU8hirH5FNQJATO+ZxCK4etXXAnQmG41NCAqANWB2\nB+2HJbH2NcQ2QHvAHUm741JGn/KI/aBlo7KEjFRDWUVUB5ji64BbUwCsMQJBAIku\nLGcjnBf/oLk+XSPZC2eGd2Ph5G5qYmH0Q2vkTx+wtTn3DV+eNsDfgMtWAJVJ5t61\ngU1QSXyhLPVlKpnnxuUCQC+xvvWjWtsLaFtAsZywJiqLxQzHts8XLGZptYJ5tLWV\nrtmYtBcJCN48RrgQHry/xWYeA4K/AFQpXfNPgprQ96Q=\n-----END RSA PRIVATE KEY-----\n",
|
||||
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7DUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5Q== Generated by Nova\n",
|
||||
"user_id": "fake"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
// ImportOutput is a sample response to a Create call that provides its own public key.
|
||||
const ImportOutput = `
|
||||
{
|
||||
"keypair": {
|
||||
"fingerprint": "1e:2c:9b:56:79:4b:45:77:f9:ca:7a:98:2c:b0:d5:3c",
|
||||
"name": "importedkey",
|
||||
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated by Nova",
|
||||
"user_id": "fake"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
// FirstKeyPair is the first result in ListOutput.
|
||||
var FirstKeyPair = KeyPair{
|
||||
Name: "firstkey",
|
||||
Fingerprint: "15:b0:f8:b3:f9:48:63:71:cf:7b:5b:38:6d:44:2d:4a",
|
||||
PublicKey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC+Eo/RZRngaGTkFs7I62ZjsIlO79KklKbMXi8F+KITD4bVQHHn+kV+4gRgkgCRbdoDqoGfpaDFs877DYX9n4z6FrAIZ4PES8TNKhatifpn9NdQYWA+IkU8CuvlEKGuFpKRi/k7JLos/gHi2hy7QUwgtRvcefvD/vgQZOVw/mGR9Q== Generated by Nova\n",
|
||||
}
|
||||
|
||||
// SecondKeyPair is the second result in ListOutput.
|
||||
var SecondKeyPair = KeyPair{
|
||||
Name: "secondkey",
|
||||
Fingerprint: "35:9d:d0:c3:4a:80:d3:d8:86:f1:ca:f7:df:c4:f9:d8",
|
||||
PublicKey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7DUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5Q== Generated by Nova\n",
|
||||
}
|
||||
|
||||
// ExpectedKeyPairSlice is the slice of results that should be parsed from ListOutput, in the expected
|
||||
// order.
|
||||
var ExpectedKeyPairSlice = []KeyPair{FirstKeyPair, SecondKeyPair}
|
||||
|
||||
// CreatedKeyPair is the parsed result from CreatedOutput.
|
||||
var CreatedKeyPair = KeyPair{
|
||||
Name: "createdkey",
|
||||
Fingerprint: "35:9d:d0:c3:4a:80:d3:d8:86:f1:ca:f7:df:c4:f9:d8",
|
||||
PublicKey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7DUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5Q== Generated by Nova\n",
|
||||
PrivateKey: "-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQC9mC3WZN9UGLxgPBpP7H5jZMc6pKwOoSgre8yun6REFktn/Kz7\nDUt9jaR1UJyRzHxITfCfAIgSxPdGqB/oF1suMyWgu5i0625vavLB5z5kC8Hq3qZJ\n9zJO1poE1kyD+htiTtPWJ88e12xuH2XB/CZN9OpEiF98hAagiOE0EnOS5QIDAQAB\nAoGAE5XO1mDhORy9COvsg+kYPUhB1GsCYxh+v88wG7HeFDKBY6KUc/Kxo6yoGn5T\nTjRjekyi2KoDZHz4VlIzyZPwFS4I1bf3oCunVoAKzgLdmnTtvRNMC5jFOGc2vUgP\n9bSyRj3S1R4ClVk2g0IDeagko/jc8zzLEYuIK+fbkds79YECQQDt3vcevgegnkga\ntF4NsDmmBPRkcSHCqrANP/7vFcBQN3czxeYYWX3DK07alu6GhH1Y4sHbdm616uU0\nll7xbDzxAkEAzAtN2IyftNygV2EGiaGgqLyo/tD9+Vui2qCQplqe4jvWh/5Sparl\nOjmKo+uAW+hLrLVMnHzRWxbWU8hirH5FNQJATO+ZxCK4etXXAnQmG41NCAqANWB2\nB+2HJbH2NcQ2QHvAHUm741JGn/KI/aBlo7KEjFRDWUVUB5ji64BbUwCsMQJBAIku\nLGcjnBf/oLk+XSPZC2eGd2Ph5G5qYmH0Q2vkTx+wtTn3DV+eNsDfgMtWAJVJ5t61\ngU1QSXyhLPVlKpnnxuUCQC+xvvWjWtsLaFtAsZywJiqLxQzHts8XLGZptYJ5tLWV\nrtmYtBcJCN48RrgQHry/xWYeA4K/AFQpXfNPgprQ96Q=\n-----END RSA PRIVATE KEY-----\n",
|
||||
UserID: "fake",
|
||||
}
|
||||
|
||||
// ImportedKeyPair is the parsed result from ImportOutput.
|
||||
var ImportedKeyPair = KeyPair{
|
||||
Name: "importedkey",
|
||||
Fingerprint: "1e:2c:9b:56:79:4b:45:77:f9:ca:7a:98:2c:b0:d5:3c",
|
||||
PublicKey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated by Nova",
|
||||
UserID: "fake",
|
||||
}
|
||||
|
||||
// HandleListSuccessfully configures the test server to respond to a List request.
|
||||
func HandleListSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/os-keypairs", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprintf(w, ListOutput)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleGetSuccessfully configures the test server to respond to a Get request for "firstkey".
|
||||
func HandleGetSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/os-keypairs/firstkey", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprintf(w, GetOutput)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleCreateSuccessfully configures the test server to respond to a Create request for a new
|
||||
// keypair called "createdkey".
|
||||
func HandleCreateSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/os-keypairs", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
th.TestJSONRequest(t, r, `{ "keypair": { "name": "createdkey" } }`)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprintf(w, CreateOutput)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleImportSuccessfully configures the test server to respond to an Import request for an
|
||||
// existing keypair called "importedkey".
|
||||
func HandleImportSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/os-keypairs", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"keypair": {
|
||||
"name": "importedkey",
|
||||
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated by Nova"
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprintf(w, ImportOutput)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleDeleteSuccessfully configures the test server to respond to a Delete request for a
|
||||
// keypair called "deletedkey".
|
||||
func HandleDeleteSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/os-keypairs/deletedkey", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "DELETE")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
})
|
||||
}
|
||||
102
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/requests.go
generated
vendored
Normal file
102
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/requests.go
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
package keypairs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// CreateOptsExt adds a KeyPair option to the base CreateOpts.
|
||||
type CreateOptsExt struct {
|
||||
servers.CreateOptsBuilder
|
||||
KeyName string `json:"key_name,omitempty"`
|
||||
}
|
||||
|
||||
// ToServerCreateMap adds the key_name and, optionally, key_data options to
|
||||
// the base server creation options.
|
||||
func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
|
||||
base, err := opts.CreateOptsBuilder.ToServerCreateMap()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if opts.KeyName == "" {
|
||||
return base, nil
|
||||
}
|
||||
|
||||
serverMap := base["server"].(map[string]interface{})
|
||||
serverMap["key_name"] = opts.KeyName
|
||||
|
||||
return base, nil
|
||||
}
|
||||
|
||||
// List returns a Pager that allows you to iterate over a collection of KeyPairs.
|
||||
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
||||
return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page {
|
||||
return KeyPairPage{pagination.SinglePageBase(r)}
|
||||
})
|
||||
}
|
||||
|
||||
// CreateOptsBuilder describes struct types that can be accepted by the Create call. Notable, the
|
||||
// CreateOpts struct in this package does.
|
||||
type CreateOptsBuilder interface {
|
||||
ToKeyPairCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// CreateOpts specifies keypair creation or import parameters.
|
||||
type CreateOpts struct {
|
||||
// Name [required] is a friendly name to refer to this KeyPair in other services.
|
||||
Name string
|
||||
|
||||
// PublicKey [optional] is a pregenerated OpenSSH-formatted public key. If provided, this key
|
||||
// will be imported and no new key will be created.
|
||||
PublicKey string
|
||||
}
|
||||
|
||||
// ToKeyPairCreateMap constructs a request body from CreateOpts.
|
||||
func (opts CreateOpts) ToKeyPairCreateMap() (map[string]interface{}, error) {
|
||||
if opts.Name == "" {
|
||||
return nil, errors.New("Missing field required for keypair creation: Name")
|
||||
}
|
||||
|
||||
keypair := make(map[string]interface{})
|
||||
keypair["name"] = opts.Name
|
||||
if opts.PublicKey != "" {
|
||||
keypair["public_key"] = opts.PublicKey
|
||||
}
|
||||
|
||||
return map[string]interface{}{"keypair": keypair}, nil
|
||||
}
|
||||
|
||||
// Create requests the creation of a new keypair on the server, or to import a pre-existing
|
||||
// keypair.
|
||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
||||
var res CreateResult
|
||||
|
||||
reqBody, err := opts.ToKeyPairCreateMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
_, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
// Get returns public data about a previously uploaded KeyPair.
|
||||
func Get(client *gophercloud.ServiceClient, name string) GetResult {
|
||||
var res GetResult
|
||||
_, res.Err = client.Get(getURL(client, name), &res.Body, nil)
|
||||
return res
|
||||
}
|
||||
|
||||
// Delete requests the deletion of a previous stored KeyPair from the server.
|
||||
func Delete(client *gophercloud.ServiceClient, name string) DeleteResult {
|
||||
var res DeleteResult
|
||||
_, res.Err = client.Delete(deleteURL(client, name), nil)
|
||||
return res
|
||||
}
|
||||
71
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/requests_test.go
generated
vendored
Normal file
71
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/requests_test.go
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
package keypairs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleListSuccessfully(t)
|
||||
|
||||
count := 0
|
||||
err := List(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
|
||||
count++
|
||||
actual, err := ExtractKeyPairs(page)
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckDeepEquals(t, ExpectedKeyPairSlice, actual)
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckEquals(t, 1, count)
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleCreateSuccessfully(t)
|
||||
|
||||
actual, err := Create(client.ServiceClient(), CreateOpts{
|
||||
Name: "createdkey",
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckDeepEquals(t, &CreatedKeyPair, actual)
|
||||
}
|
||||
|
||||
func TestImport(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleImportSuccessfully(t)
|
||||
|
||||
actual, err := Create(client.ServiceClient(), CreateOpts{
|
||||
Name: "importedkey",
|
||||
PublicKey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated by Nova",
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckDeepEquals(t, &ImportedKeyPair, actual)
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleGetSuccessfully(t)
|
||||
|
||||
actual, err := Get(client.ServiceClient(), "firstkey").Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckDeepEquals(t, &FirstKeyPair, actual)
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleDeleteSuccessfully(t)
|
||||
|
||||
err := Delete(client.ServiceClient(), "deletedkey").ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
94
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/results.go
generated
vendored
Normal file
94
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/results.go
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
package keypairs
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// KeyPair is an SSH key known to the OpenStack cluster that is available to be injected into
|
||||
// servers.
|
||||
type KeyPair struct {
|
||||
// Name is used to refer to this keypair from other services within this region.
|
||||
Name string `mapstructure:"name"`
|
||||
|
||||
// Fingerprint is a short sequence of bytes that can be used to authenticate or validate a longer
|
||||
// public key.
|
||||
Fingerprint string `mapstructure:"fingerprint"`
|
||||
|
||||
// PublicKey is the public key from this pair, in OpenSSH format. "ssh-rsa AAAAB3Nz..."
|
||||
PublicKey string `mapstructure:"public_key"`
|
||||
|
||||
// PrivateKey is the private key from this pair, in PEM format.
|
||||
// "-----BEGIN RSA PRIVATE KEY-----\nMIICXA..." It is only present if this keypair was just
|
||||
// returned from a Create call
|
||||
PrivateKey string `mapstructure:"private_key"`
|
||||
|
||||
// UserID is the user who owns this keypair.
|
||||
UserID string `mapstructure:"user_id"`
|
||||
}
|
||||
|
||||
// KeyPairPage stores a single, only page of KeyPair results from a List call.
|
||||
type KeyPairPage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
|
||||
// IsEmpty determines whether or not a KeyPairPage is empty.
|
||||
func (page KeyPairPage) IsEmpty() (bool, error) {
|
||||
ks, err := ExtractKeyPairs(page)
|
||||
return len(ks) == 0, err
|
||||
}
|
||||
|
||||
// ExtractKeyPairs interprets a page of results as a slice of KeyPairs.
|
||||
func ExtractKeyPairs(page pagination.Page) ([]KeyPair, error) {
|
||||
type pair struct {
|
||||
KeyPair KeyPair `mapstructure:"keypair"`
|
||||
}
|
||||
|
||||
var resp struct {
|
||||
KeyPairs []pair `mapstructure:"keypairs"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(page.(KeyPairPage).Body, &resp)
|
||||
results := make([]KeyPair, len(resp.KeyPairs))
|
||||
for i, pair := range resp.KeyPairs {
|
||||
results[i] = pair.KeyPair
|
||||
}
|
||||
return results, err
|
||||
}
|
||||
|
||||
type keyPairResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract is a method that attempts to interpret any KeyPair resource response as a KeyPair struct.
|
||||
func (r keyPairResult) Extract() (*KeyPair, error) {
|
||||
if r.Err != nil {
|
||||
return nil, r.Err
|
||||
}
|
||||
|
||||
var res struct {
|
||||
KeyPair *KeyPair `json:"keypair" mapstructure:"keypair"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(r.Body, &res)
|
||||
return res.KeyPair, err
|
||||
}
|
||||
|
||||
// CreateResult is the response from a Create operation. Call its Extract method to interpret it
|
||||
// as a KeyPair.
|
||||
type CreateResult struct {
|
||||
keyPairResult
|
||||
}
|
||||
|
||||
// GetResult is the response from a Get operation. Call its Extract method to interpret it
|
||||
// as a KeyPair.
|
||||
type GetResult struct {
|
||||
keyPairResult
|
||||
}
|
||||
|
||||
// DeleteResult is the response from a Delete operation. Call its Extract method to determine if
|
||||
// the call succeeded or failed.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
25
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/urls.go
generated
vendored
Normal file
25
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/urls.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
package keypairs
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
const resourcePath = "os-keypairs"
|
||||
|
||||
func resourceURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL(resourcePath)
|
||||
}
|
||||
|
||||
func listURL(c *gophercloud.ServiceClient) string {
|
||||
return resourceURL(c)
|
||||
}
|
||||
|
||||
func createURL(c *gophercloud.ServiceClient) string {
|
||||
return resourceURL(c)
|
||||
}
|
||||
|
||||
func getURL(c *gophercloud.ServiceClient, name string) string {
|
||||
return c.ServiceURL(resourcePath, name)
|
||||
}
|
||||
|
||||
func deleteURL(c *gophercloud.ServiceClient, name string) string {
|
||||
return getURL(c, name)
|
||||
}
|
||||
40
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/urls_test.go
generated
vendored
Normal file
40
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs/urls_test.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
package keypairs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
func TestListURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"os-keypairs", listURL(c))
|
||||
}
|
||||
|
||||
func TestCreateURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"os-keypairs", createURL(c))
|
||||
}
|
||||
|
||||
func TestGetURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"os-keypairs/wat", getURL(c, "wat"))
|
||||
}
|
||||
|
||||
func TestDeleteURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"os-keypairs/wat", deleteURL(c, "wat"))
|
||||
}
|
||||
1
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/doc.go
generated
vendored
Normal file
1
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/doc.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package secgroups
|
||||
265
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/fixtures.go
generated
vendored
Normal file
265
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,265 @@
|
||||
package secgroups
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
fake "github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
const rootPath = "/os-security-groups"
|
||||
|
||||
const listGroupsJSON = `
|
||||
{
|
||||
"security_groups": [
|
||||
{
|
||||
"description": "default",
|
||||
"id": "{groupID}",
|
||||
"name": "default",
|
||||
"rules": [],
|
||||
"tenant_id": "openstack"
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
func mockListGroupsResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, listGroupsJSON)
|
||||
})
|
||||
}
|
||||
|
||||
func mockListGroupsByServerResponse(t *testing.T, serverID string) {
|
||||
url := fmt.Sprintf("/servers/%s%s", serverID, rootPath)
|
||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, listGroupsJSON)
|
||||
})
|
||||
}
|
||||
|
||||
func mockCreateGroupResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"security_group": {
|
||||
"name": "test",
|
||||
"description": "something"
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"security_group": {
|
||||
"description": "something",
|
||||
"id": "{groupID}",
|
||||
"name": "test",
|
||||
"rules": [],
|
||||
"tenant_id": "openstack"
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func mockUpdateGroupResponse(t *testing.T, groupID string) {
|
||||
url := fmt.Sprintf("%s/%s", rootPath, groupID)
|
||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "PUT")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"security_group": {
|
||||
"name": "new_name",
|
||||
"description": "new_desc"
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"security_group": {
|
||||
"description": "something",
|
||||
"id": "{groupID}",
|
||||
"name": "new_name",
|
||||
"rules": [],
|
||||
"tenant_id": "openstack"
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func mockGetGroupsResponse(t *testing.T, groupID string) {
|
||||
url := fmt.Sprintf("%s/%s", rootPath, groupID)
|
||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"security_group": {
|
||||
"description": "default",
|
||||
"id": "{groupID}",
|
||||
"name": "default",
|
||||
"rules": [
|
||||
{
|
||||
"from_port": 80,
|
||||
"group": {
|
||||
"tenant_id": "openstack",
|
||||
"name": "default"
|
||||
},
|
||||
"ip_protocol": "TCP",
|
||||
"to_port": 85,
|
||||
"parent_group_id": "{groupID}",
|
||||
"ip_range": {
|
||||
"cidr": "0.0.0.0"
|
||||
},
|
||||
"id": "{ruleID}"
|
||||
}
|
||||
],
|
||||
"tenant_id": "openstack"
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func mockGetNumericIDGroupResponse(t *testing.T, groupID int) {
|
||||
url := fmt.Sprintf("%s/%d", rootPath, groupID)
|
||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"security_group": {
|
||||
"id": 12345
|
||||
}
|
||||
}
|
||||
`)
|
||||
})
|
||||
}
|
||||
|
||||
func mockDeleteGroupResponse(t *testing.T, groupID string) {
|
||||
url := fmt.Sprintf("%s/%s", rootPath, groupID)
|
||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "DELETE")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
})
|
||||
}
|
||||
|
||||
func mockAddRuleResponse(t *testing.T) {
|
||||
th.Mux.HandleFunc("/os-security-group-rules", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"security_group_rule": {
|
||||
"from_port": 22,
|
||||
"ip_protocol": "TCP",
|
||||
"to_port": 22,
|
||||
"parent_group_id": "{groupID}",
|
||||
"cidr": "0.0.0.0/0"
|
||||
}
|
||||
} `)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
fmt.Fprintf(w, `
|
||||
{
|
||||
"security_group_rule": {
|
||||
"from_port": 22,
|
||||
"group": {},
|
||||
"ip_protocol": "TCP",
|
||||
"to_port": 22,
|
||||
"parent_group_id": "{groupID}",
|
||||
"ip_range": {
|
||||
"cidr": "0.0.0.0/0"
|
||||
},
|
||||
"id": "{ruleID}"
|
||||
}
|
||||
}`)
|
||||
})
|
||||
}
|
||||
|
||||
func mockDeleteRuleResponse(t *testing.T, ruleID string) {
|
||||
url := fmt.Sprintf("/os-security-group-rules/%s", ruleID)
|
||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "DELETE")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
})
|
||||
}
|
||||
|
||||
func mockAddServerToGroupResponse(t *testing.T, serverID string) {
|
||||
url := fmt.Sprintf("/servers/%s/action", serverID)
|
||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"addSecurityGroup": {
|
||||
"name": "test"
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
})
|
||||
}
|
||||
|
||||
func mockRemoveServerFromGroupResponse(t *testing.T, serverID string) {
|
||||
url := fmt.Sprintf("/servers/%s/action", serverID)
|
||||
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
|
||||
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"removeSecurityGroup": {
|
||||
"name": "test"
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
})
|
||||
}
|
||||
257
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/requests.go
generated
vendored
Normal file
257
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/requests.go
generated
vendored
Normal file
@@ -0,0 +1,257 @@
|
||||
package secgroups
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
func commonList(client *gophercloud.ServiceClient, url string) pagination.Pager {
|
||||
createPage := func(r pagination.PageResult) pagination.Page {
|
||||
return SecurityGroupPage{pagination.SinglePageBase(r)}
|
||||
}
|
||||
|
||||
return pagination.NewPager(client, url, createPage)
|
||||
}
|
||||
|
||||
// List will return a collection of all the security groups for a particular
|
||||
// tenant.
|
||||
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
||||
return commonList(client, rootURL(client))
|
||||
}
|
||||
|
||||
// ListByServer will return a collection of all the security groups which are
|
||||
// associated with a particular server.
|
||||
func ListByServer(client *gophercloud.ServiceClient, serverID string) pagination.Pager {
|
||||
return commonList(client, listByServerURL(client, serverID))
|
||||
}
|
||||
|
||||
// GroupOpts is the underlying struct responsible for creating or updating
|
||||
// security groups. It therefore represents the mutable attributes of a
|
||||
// security group.
|
||||
type GroupOpts struct {
|
||||
// Required - the name of your security group.
|
||||
Name string `json:"name"`
|
||||
|
||||
// Required - the description of your security group.
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// CreateOpts is the struct responsible for creating a security group.
|
||||
type CreateOpts GroupOpts
|
||||
|
||||
// CreateOptsBuilder builds the create options into a serializable format.
|
||||
type CreateOptsBuilder interface {
|
||||
ToSecGroupCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
var (
|
||||
errName = errors.New("Name is a required field")
|
||||
errDesc = errors.New("Description is a required field")
|
||||
)
|
||||
|
||||
// ToSecGroupCreateMap builds the create options into a serializable format.
|
||||
func (opts CreateOpts) ToSecGroupCreateMap() (map[string]interface{}, error) {
|
||||
sg := make(map[string]interface{})
|
||||
|
||||
if opts.Name == "" {
|
||||
return sg, errName
|
||||
}
|
||||
if opts.Description == "" {
|
||||
return sg, errDesc
|
||||
}
|
||||
|
||||
sg["name"] = opts.Name
|
||||
sg["description"] = opts.Description
|
||||
|
||||
return map[string]interface{}{"security_group": sg}, nil
|
||||
}
|
||||
|
||||
// Create will create a new security group.
|
||||
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
||||
var result CreateResult
|
||||
|
||||
reqBody, err := opts.ToSecGroupCreateMap()
|
||||
if err != nil {
|
||||
result.Err = err
|
||||
return result
|
||||
}
|
||||
|
||||
_, result.Err = client.Post(rootURL(client), reqBody, &result.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// UpdateOpts is the struct responsible for updating an existing security group.
|
||||
type UpdateOpts GroupOpts
|
||||
|
||||
// UpdateOptsBuilder builds the update options into a serializable format.
|
||||
type UpdateOptsBuilder interface {
|
||||
ToSecGroupUpdateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// ToSecGroupUpdateMap builds the update options into a serializable format.
|
||||
func (opts UpdateOpts) ToSecGroupUpdateMap() (map[string]interface{}, error) {
|
||||
sg := make(map[string]interface{})
|
||||
|
||||
if opts.Name == "" {
|
||||
return sg, errName
|
||||
}
|
||||
if opts.Description == "" {
|
||||
return sg, errDesc
|
||||
}
|
||||
|
||||
sg["name"] = opts.Name
|
||||
sg["description"] = opts.Description
|
||||
|
||||
return map[string]interface{}{"security_group": sg}, nil
|
||||
}
|
||||
|
||||
// Update will modify the mutable properties of a security group, notably its
|
||||
// name and description.
|
||||
func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
|
||||
var result UpdateResult
|
||||
|
||||
reqBody, err := opts.ToSecGroupUpdateMap()
|
||||
if err != nil {
|
||||
result.Err = err
|
||||
return result
|
||||
}
|
||||
|
||||
_, result.Err = client.Put(resourceURL(client, id), reqBody, &result.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Get will return details for a particular security group.
|
||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||
var result GetResult
|
||||
_, result.Err = client.Get(resourceURL(client, id), &result.Body, nil)
|
||||
return result
|
||||
}
|
||||
|
||||
// Delete will permanently delete a security group from the project.
|
||||
func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
||||
var result gophercloud.ErrResult
|
||||
_, result.Err = client.Delete(resourceURL(client, id), nil)
|
||||
return result
|
||||
}
|
||||
|
||||
// CreateRuleOpts represents the configuration for adding a new rule to an
|
||||
// existing security group.
|
||||
type CreateRuleOpts struct {
|
||||
// Required - the ID of the group that this rule will be added to.
|
||||
ParentGroupID string `json:"parent_group_id"`
|
||||
|
||||
// Required - the lower bound of the port range that will be opened.
|
||||
FromPort int `json:"from_port"`
|
||||
|
||||
// Required - the upper bound of the port range that will be opened.
|
||||
ToPort int `json:"to_port"`
|
||||
|
||||
// Required - the protocol type that will be allowed, e.g. TCP.
|
||||
IPProtocol string `json:"ip_protocol"`
|
||||
|
||||
// ONLY required if FromGroupID is blank. This represents the IP range that
|
||||
// will be the source of network traffic to your security group. Use
|
||||
// 0.0.0.0/0 to allow all IP addresses.
|
||||
CIDR string `json:"cidr,omitempty"`
|
||||
|
||||
// ONLY required if CIDR is blank. This value represents the ID of a group
|
||||
// that forwards traffic to the parent group. So, instead of accepting
|
||||
// network traffic from an entire IP range, you can instead refine the
|
||||
// inbound source by an existing security group.
|
||||
FromGroupID string `json:"group_id,omitempty"`
|
||||
}
|
||||
|
||||
// CreateRuleOptsBuilder builds the create rule options into a serializable format.
|
||||
type CreateRuleOptsBuilder interface {
|
||||
ToRuleCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// ToRuleCreateMap builds the create rule options into a serializable format.
|
||||
func (opts CreateRuleOpts) ToRuleCreateMap() (map[string]interface{}, error) {
|
||||
rule := make(map[string]interface{})
|
||||
|
||||
if opts.ParentGroupID == "" {
|
||||
return rule, errors.New("A ParentGroupID must be set")
|
||||
}
|
||||
if opts.FromPort == 0 {
|
||||
return rule, errors.New("A FromPort must be set")
|
||||
}
|
||||
if opts.ToPort == 0 {
|
||||
return rule, errors.New("A ToPort must be set")
|
||||
}
|
||||
if opts.IPProtocol == "" {
|
||||
return rule, errors.New("A IPProtocol must be set")
|
||||
}
|
||||
if opts.CIDR == "" && opts.FromGroupID == "" {
|
||||
return rule, errors.New("A CIDR or FromGroupID must be set")
|
||||
}
|
||||
|
||||
rule["parent_group_id"] = opts.ParentGroupID
|
||||
rule["from_port"] = opts.FromPort
|
||||
rule["to_port"] = opts.ToPort
|
||||
rule["ip_protocol"] = opts.IPProtocol
|
||||
|
||||
if opts.CIDR != "" {
|
||||
rule["cidr"] = opts.CIDR
|
||||
}
|
||||
if opts.FromGroupID != "" {
|
||||
rule["group_id"] = opts.FromGroupID
|
||||
}
|
||||
|
||||
return map[string]interface{}{"security_group_rule": rule}, nil
|
||||
}
|
||||
|
||||
// CreateRule will add a new rule to an existing security group (whose ID is
|
||||
// specified in CreateRuleOpts). You have the option of controlling inbound
|
||||
// traffic from either an IP range (CIDR) or from another security group.
|
||||
func CreateRule(client *gophercloud.ServiceClient, opts CreateRuleOptsBuilder) CreateRuleResult {
|
||||
var result CreateRuleResult
|
||||
|
||||
reqBody, err := opts.ToRuleCreateMap()
|
||||
if err != nil {
|
||||
result.Err = err
|
||||
return result
|
||||
}
|
||||
|
||||
_, result.Err = client.Post(rootRuleURL(client), reqBody, &result.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// DeleteRule will permanently delete a rule from a security group.
|
||||
func DeleteRule(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
||||
var result gophercloud.ErrResult
|
||||
_, result.Err = client.Delete(resourceRuleURL(client, id), nil)
|
||||
return result
|
||||
}
|
||||
|
||||
func actionMap(prefix, groupName string) map[string]map[string]string {
|
||||
return map[string]map[string]string{
|
||||
prefix + "SecurityGroup": map[string]string{"name": groupName},
|
||||
}
|
||||
}
|
||||
|
||||
// AddServerToGroup will associate a server and a security group, enforcing the
|
||||
// rules of the group on the server.
|
||||
func AddServerToGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult {
|
||||
var result gophercloud.ErrResult
|
||||
_, result.Err = client.Post(serverActionURL(client, serverID), actionMap("add", groupName), &result.Body, nil)
|
||||
return result
|
||||
}
|
||||
|
||||
// RemoveServerFromGroup will disassociate a server from a security group.
|
||||
func RemoveServerFromGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult {
|
||||
var result gophercloud.ErrResult
|
||||
_, result.Err = client.Post(serverActionURL(client, serverID), actionMap("remove", groupName), &result.Body, nil)
|
||||
return result
|
||||
}
|
||||
248
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/requests_test.go
generated
vendored
Normal file
248
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/requests_test.go
generated
vendored
Normal file
@@ -0,0 +1,248 @@
|
||||
package secgroups
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
const (
|
||||
serverID = "{serverID}"
|
||||
groupID = "{groupID}"
|
||||
ruleID = "{ruleID}"
|
||||
)
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
mockListGroupsResponse(t)
|
||||
|
||||
count := 0
|
||||
|
||||
err := List(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
|
||||
count++
|
||||
actual, err := ExtractSecurityGroups(page)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to extract users: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
expected := []SecurityGroup{
|
||||
SecurityGroup{
|
||||
ID: groupID,
|
||||
Description: "default",
|
||||
Name: "default",
|
||||
Rules: []Rule{},
|
||||
TenantID: "openstack",
|
||||
},
|
||||
}
|
||||
|
||||
th.CheckDeepEquals(t, expected, actual)
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
th.AssertEquals(t, 1, count)
|
||||
}
|
||||
|
||||
func TestListByServer(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
mockListGroupsByServerResponse(t, serverID)
|
||||
|
||||
count := 0
|
||||
|
||||
err := ListByServer(client.ServiceClient(), serverID).EachPage(func(page pagination.Page) (bool, error) {
|
||||
count++
|
||||
actual, err := ExtractSecurityGroups(page)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to extract users: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
expected := []SecurityGroup{
|
||||
SecurityGroup{
|
||||
ID: groupID,
|
||||
Description: "default",
|
||||
Name: "default",
|
||||
Rules: []Rule{},
|
||||
TenantID: "openstack",
|
||||
},
|
||||
}
|
||||
|
||||
th.CheckDeepEquals(t, expected, actual)
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
th.AssertNoErr(t, err)
|
||||
th.AssertEquals(t, 1, count)
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
mockCreateGroupResponse(t)
|
||||
|
||||
opts := CreateOpts{
|
||||
Name: "test",
|
||||
Description: "something",
|
||||
}
|
||||
|
||||
group, err := Create(client.ServiceClient(), opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
expected := &SecurityGroup{
|
||||
ID: groupID,
|
||||
Name: "test",
|
||||
Description: "something",
|
||||
TenantID: "openstack",
|
||||
Rules: []Rule{},
|
||||
}
|
||||
th.AssertDeepEquals(t, expected, group)
|
||||
}
|
||||
|
||||
func TestUpdate(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
mockUpdateGroupResponse(t, groupID)
|
||||
|
||||
opts := UpdateOpts{
|
||||
Name: "new_name",
|
||||
Description: "new_desc",
|
||||
}
|
||||
|
||||
group, err := Update(client.ServiceClient(), groupID, opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
expected := &SecurityGroup{
|
||||
ID: groupID,
|
||||
Name: "new_name",
|
||||
Description: "something",
|
||||
TenantID: "openstack",
|
||||
Rules: []Rule{},
|
||||
}
|
||||
th.AssertDeepEquals(t, expected, group)
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
mockGetGroupsResponse(t, groupID)
|
||||
|
||||
group, err := Get(client.ServiceClient(), groupID).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
expected := &SecurityGroup{
|
||||
ID: groupID,
|
||||
Description: "default",
|
||||
Name: "default",
|
||||
TenantID: "openstack",
|
||||
Rules: []Rule{
|
||||
Rule{
|
||||
FromPort: 80,
|
||||
ToPort: 85,
|
||||
IPProtocol: "TCP",
|
||||
IPRange: IPRange{CIDR: "0.0.0.0"},
|
||||
Group: Group{TenantID: "openstack", Name: "default"},
|
||||
ParentGroupID: groupID,
|
||||
ID: ruleID,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
th.AssertDeepEquals(t, expected, group)
|
||||
}
|
||||
|
||||
func TestGetNumericID(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
numericGroupID := 12345
|
||||
|
||||
mockGetNumericIDGroupResponse(t, numericGroupID)
|
||||
|
||||
group, err := Get(client.ServiceClient(), "12345").Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
expected := &SecurityGroup{ID: "12345"}
|
||||
th.AssertDeepEquals(t, expected, group)
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
mockDeleteGroupResponse(t, groupID)
|
||||
|
||||
err := Delete(client.ServiceClient(), groupID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func TestAddRule(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
mockAddRuleResponse(t)
|
||||
|
||||
opts := CreateRuleOpts{
|
||||
ParentGroupID: groupID,
|
||||
FromPort: 22,
|
||||
ToPort: 22,
|
||||
IPProtocol: "TCP",
|
||||
CIDR: "0.0.0.0/0",
|
||||
}
|
||||
|
||||
rule, err := CreateRule(client.ServiceClient(), opts).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
|
||||
expected := &Rule{
|
||||
FromPort: 22,
|
||||
ToPort: 22,
|
||||
Group: Group{},
|
||||
IPProtocol: "TCP",
|
||||
ParentGroupID: groupID,
|
||||
IPRange: IPRange{CIDR: "0.0.0.0/0"},
|
||||
ID: ruleID,
|
||||
}
|
||||
|
||||
th.AssertDeepEquals(t, expected, rule)
|
||||
}
|
||||
|
||||
func TestDeleteRule(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
mockDeleteRuleResponse(t, ruleID)
|
||||
|
||||
err := DeleteRule(client.ServiceClient(), ruleID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func TestAddServer(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
mockAddServerToGroupResponse(t, serverID)
|
||||
|
||||
err := AddServerToGroup(client.ServiceClient(), serverID, "test").ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func TestRemoveServer(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
mockRemoveServerFromGroupResponse(t, serverID)
|
||||
|
||||
err := RemoveServerFromGroup(client.ServiceClient(), serverID, "test").ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
147
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/results.go
generated
vendored
Normal file
147
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/results.go
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
package secgroups
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// SecurityGroup represents a security group.
|
||||
type SecurityGroup struct {
|
||||
// The unique ID of the group. If Neutron is installed, this ID will be
|
||||
// represented as a string UUID; if Neutron is not installed, it will be a
|
||||
// numeric ID. For the sake of consistency, we always cast it to a string.
|
||||
ID string
|
||||
|
||||
// The human-readable name of the group, which needs to be unique.
|
||||
Name string
|
||||
|
||||
// The human-readable description of the group.
|
||||
Description string
|
||||
|
||||
// The rules which determine how this security group operates.
|
||||
Rules []Rule
|
||||
|
||||
// The ID of the tenant to which this security group belongs.
|
||||
TenantID string `mapstructure:"tenant_id"`
|
||||
}
|
||||
|
||||
// Rule represents a security group rule, a policy which determines how a
|
||||
// security group operates and what inbound traffic it allows in.
|
||||
type Rule struct {
|
||||
// The unique ID. If Neutron is installed, this ID will be
|
||||
// represented as a string UUID; if Neutron is not installed, it will be a
|
||||
// numeric ID. For the sake of consistency, we always cast it to a string.
|
||||
ID string
|
||||
|
||||
// The lower bound of the port range which this security group should open up
|
||||
FromPort int `mapstructure:"from_port"`
|
||||
|
||||
// The upper bound of the port range which this security group should open up
|
||||
ToPort int `mapstructure:"to_port"`
|
||||
|
||||
// The IP protocol (e.g. TCP) which the security group accepts
|
||||
IPProtocol string `mapstructure:"ip_protocol"`
|
||||
|
||||
// The CIDR IP range whose traffic can be received
|
||||
IPRange IPRange `mapstructure:"ip_range"`
|
||||
|
||||
// The security group ID to which this rule belongs
|
||||
ParentGroupID string `mapstructure:"parent_group_id"`
|
||||
|
||||
// Not documented.
|
||||
Group Group
|
||||
}
|
||||
|
||||
// IPRange represents the IP range whose traffic will be accepted by the
|
||||
// security group.
|
||||
type IPRange struct {
|
||||
CIDR string
|
||||
}
|
||||
|
||||
// Group represents a group.
|
||||
type Group struct {
|
||||
TenantID string `mapstructure:"tenant_id"`
|
||||
Name string
|
||||
}
|
||||
|
||||
// SecurityGroupPage is a single page of a SecurityGroup collection.
|
||||
type SecurityGroupPage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
|
||||
// IsEmpty determines whether or not a page of Security Groups contains any results.
|
||||
func (page SecurityGroupPage) IsEmpty() (bool, error) {
|
||||
users, err := ExtractSecurityGroups(page)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return len(users) == 0, nil
|
||||
}
|
||||
|
||||
// ExtractSecurityGroups returns a slice of SecurityGroups contained in a single page of results.
|
||||
func ExtractSecurityGroups(page pagination.Page) ([]SecurityGroup, error) {
|
||||
casted := page.(SecurityGroupPage).Body
|
||||
var response struct {
|
||||
SecurityGroups []SecurityGroup `mapstructure:"security_groups"`
|
||||
}
|
||||
|
||||
err := mapstructure.WeakDecode(casted, &response)
|
||||
|
||||
return response.SecurityGroups, err
|
||||
}
|
||||
|
||||
type commonResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// Extract will extract a SecurityGroup struct from most responses.
|
||||
func (r commonResult) Extract() (*SecurityGroup, error) {
|
||||
if r.Err != nil {
|
||||
return nil, r.Err
|
||||
}
|
||||
|
||||
var response struct {
|
||||
SecurityGroup SecurityGroup `mapstructure:"security_group"`
|
||||
}
|
||||
|
||||
err := mapstructure.WeakDecode(r.Body, &response)
|
||||
|
||||
return &response.SecurityGroup, err
|
||||
}
|
||||
|
||||
// CreateRuleResult represents the result when adding rules to a security group.
|
||||
type CreateRuleResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract will extract a Rule struct from a CreateRuleResult.
|
||||
func (r CreateRuleResult) Extract() (*Rule, error) {
|
||||
if r.Err != nil {
|
||||
return nil, r.Err
|
||||
}
|
||||
|
||||
var response struct {
|
||||
Rule Rule `mapstructure:"security_group_rule"`
|
||||
}
|
||||
|
||||
err := mapstructure.WeakDecode(r.Body, &response)
|
||||
|
||||
return &response.Rule, err
|
||||
}
|
||||
32
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/urls.go
generated
vendored
Normal file
32
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups/urls.go
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
package secgroups
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
const (
|
||||
secgrouppath = "os-security-groups"
|
||||
rulepath = "os-security-group-rules"
|
||||
)
|
||||
|
||||
func resourceURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return c.ServiceURL(secgrouppath, id)
|
||||
}
|
||||
|
||||
func rootURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL(secgrouppath)
|
||||
}
|
||||
|
||||
func listByServerURL(c *gophercloud.ServiceClient, serverID string) string {
|
||||
return c.ServiceURL("servers", serverID, secgrouppath)
|
||||
}
|
||||
|
||||
func rootRuleURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL(rulepath)
|
||||
}
|
||||
|
||||
func resourceRuleURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return c.ServiceURL(rulepath, id)
|
||||
}
|
||||
|
||||
func serverActionURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return c.ServiceURL("servers", id, "action")
|
||||
}
|
||||
5
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/doc.go
generated
vendored
Normal file
5
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/doc.go
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Package startstop provides functionality to start and stop servers that have
|
||||
been provisioned by the OpenStack Compute service.
|
||||
*/
|
||||
package startstop
|
||||
27
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/fixtures.go
generated
vendored
Normal file
27
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package startstop
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
func mockStartServerResponse(t *testing.T, id string) {
|
||||
th.Mux.HandleFunc("/servers/"+id+"/action", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
th.TestJSONRequest(t, r, `{"os-start": null}`)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
})
|
||||
}
|
||||
|
||||
func mockStopServerResponse(t *testing.T, id string) {
|
||||
th.Mux.HandleFunc("/servers/"+id+"/action", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
th.TestJSONRequest(t, r, `{"os-stop": null}`)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
})
|
||||
}
|
||||
23
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/requests.go
generated
vendored
Normal file
23
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/requests.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
package startstop
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
func actionURL(client *gophercloud.ServiceClient, id string) string {
|
||||
return client.ServiceURL("servers", id, "action")
|
||||
}
|
||||
|
||||
// Start is the operation responsible for starting a Compute server.
|
||||
func Start(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
||||
var res gophercloud.ErrResult
|
||||
reqBody := map[string]interface{}{"os-start": nil}
|
||||
_, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil)
|
||||
return res
|
||||
}
|
||||
|
||||
// Stop is the operation responsible for stopping a Compute server.
|
||||
func Stop(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
|
||||
var res gophercloud.ErrResult
|
||||
reqBody := map[string]interface{}{"os-stop": nil}
|
||||
_, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil)
|
||||
return res
|
||||
}
|
||||
30
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/requests_test.go
generated
vendored
Normal file
30
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop/requests_test.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
package startstop
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
const serverID = "{serverId}"
|
||||
|
||||
func TestStart(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
mockStartServerResponse(t, serverID)
|
||||
|
||||
err := Start(client.ServiceClient(), serverID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
|
||||
func TestStop(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
|
||||
mockStopServerResponse(t, serverID)
|
||||
|
||||
err := Stop(client.ServiceClient(), serverID).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
2
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/doc.go
generated
vendored
Normal file
2
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/doc.go
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package tenantnetworks provides the ability for tenants to see information about the networks they have access to
|
||||
package tenantnetworks
|
||||
84
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/fixtures.go
generated
vendored
Normal file
84
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
// +build fixtures
|
||||
|
||||
package tenantnetworks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
// ListOutput is a sample response to a List call.
|
||||
const ListOutput = `
|
||||
{
|
||||
"networks": [
|
||||
{
|
||||
"cidr": "10.0.0.0/29",
|
||||
"id": "20c8acc0-f747-4d71-a389-46d078ebf047",
|
||||
"label": "mynet_0"
|
||||
},
|
||||
{
|
||||
"cidr": "10.0.0.10/29",
|
||||
"id": "20c8acc0-f747-4d71-a389-46d078ebf000",
|
||||
"label": "mynet_1"
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
// GetOutput is a sample response to a Get call.
|
||||
const GetOutput = `
|
||||
{
|
||||
"network": {
|
||||
"cidr": "10.0.0.10/29",
|
||||
"id": "20c8acc0-f747-4d71-a389-46d078ebf000",
|
||||
"label": "mynet_1"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
// FirstNetwork is the first result in ListOutput.
|
||||
var nilTime time.Time
|
||||
var FirstNetwork = Network{
|
||||
CIDR: "10.0.0.0/29",
|
||||
ID: "20c8acc0-f747-4d71-a389-46d078ebf047",
|
||||
Name: "mynet_0",
|
||||
}
|
||||
|
||||
// SecondNetwork is the second result in ListOutput.
|
||||
var SecondNetwork = Network{
|
||||
CIDR: "10.0.0.10/29",
|
||||
ID: "20c8acc0-f747-4d71-a389-46d078ebf000",
|
||||
Name: "mynet_1",
|
||||
}
|
||||
|
||||
// ExpectedNetworkSlice is the slice of results that should be parsed
|
||||
// from ListOutput, in the expected order.
|
||||
var ExpectedNetworkSlice = []Network{FirstNetwork, SecondNetwork}
|
||||
|
||||
// HandleListSuccessfully configures the test server to respond to a List request.
|
||||
func HandleListSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/os-tenant-networks", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprintf(w, ListOutput)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleGetSuccessfully configures the test server to respond to a Get request
|
||||
// for an existing network.
|
||||
func HandleGetSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/os-tenant-networks/20c8acc0-f747-4d71-a389-46d078ebf000", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprintf(w, GetOutput)
|
||||
})
|
||||
}
|
||||
22
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/requests.go
generated
vendored
Normal file
22
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/requests.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
package tenantnetworks
|
||||
|
||||
import (
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// List returns a Pager that allows you to iterate over a collection of Network.
|
||||
func List(client *gophercloud.ServiceClient) pagination.Pager {
|
||||
url := listURL(client)
|
||||
createPage := func(r pagination.PageResult) pagination.Page {
|
||||
return NetworkPage{pagination.SinglePageBase(r)}
|
||||
}
|
||||
return pagination.NewPager(client, url, createPage)
|
||||
}
|
||||
|
||||
// Get returns data about a previously created Network.
|
||||
func Get(client *gophercloud.ServiceClient, id string) GetResult {
|
||||
var res GetResult
|
||||
_, res.Err = client.Get(getURL(client, id), &res.Body, nil)
|
||||
return res
|
||||
}
|
||||
37
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/requests_test.go
generated
vendored
Normal file
37
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/requests_test.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
package tenantnetworks
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleListSuccessfully(t)
|
||||
|
||||
count := 0
|
||||
err := List(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
|
||||
count++
|
||||
actual, err := ExtractNetworks(page)
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckDeepEquals(t, ExpectedNetworkSlice, actual)
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckEquals(t, 1, count)
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleGetSuccessfully(t)
|
||||
|
||||
actual, err := Get(client.ServiceClient(), "20c8acc0-f747-4d71-a389-46d078ebf000").Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckDeepEquals(t, &SecondNetwork, actual)
|
||||
}
|
||||
68
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/results.go
generated
vendored
Normal file
68
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/results.go
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
package tenantnetworks
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// A Network represents a nova-network that an instance communicates on
|
||||
type Network struct {
|
||||
// CIDR is the IPv4 subnet.
|
||||
CIDR string `mapstructure:"cidr"`
|
||||
|
||||
// ID is the UUID of the network.
|
||||
ID string `mapstructure:"id"`
|
||||
|
||||
// Name is the common name that the network has.
|
||||
Name string `mapstructure:"label"`
|
||||
}
|
||||
|
||||
// NetworkPage stores a single, only page of Networks
|
||||
// results from a List call.
|
||||
type NetworkPage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
|
||||
// IsEmpty determines whether or not a NetworkPage is empty.
|
||||
func (page NetworkPage) IsEmpty() (bool, error) {
|
||||
va, err := ExtractNetworks(page)
|
||||
return len(va) == 0, err
|
||||
}
|
||||
|
||||
// ExtractNetworks interprets a page of results as a slice of Networks
|
||||
func ExtractNetworks(page pagination.Page) ([]Network, error) {
|
||||
networks := page.(NetworkPage).Body
|
||||
var res struct {
|
||||
Networks []Network `mapstructure:"networks"`
|
||||
}
|
||||
|
||||
err := mapstructure.WeakDecode(networks, &res)
|
||||
|
||||
return res.Networks, err
|
||||
}
|
||||
|
||||
type NetworkResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract is a method that attempts to interpret any Network resource
|
||||
// response as a Network struct.
|
||||
func (r NetworkResult) Extract() (*Network, error) {
|
||||
if r.Err != nil {
|
||||
return nil, r.Err
|
||||
}
|
||||
|
||||
var res struct {
|
||||
Network *Network `json:"network" mapstructure:"network"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(r.Body, &res)
|
||||
return res.Network, err
|
||||
}
|
||||
|
||||
// GetResult is the response from a Get operation. Call its Extract method to interpret it
|
||||
// as a Network.
|
||||
type GetResult struct {
|
||||
NetworkResult
|
||||
}
|
||||
17
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/urls.go
generated
vendored
Normal file
17
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/urls.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
package tenantnetworks
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
const resourcePath = "os-tenant-networks"
|
||||
|
||||
func resourceURL(c *gophercloud.ServiceClient) string {
|
||||
return c.ServiceURL(resourcePath)
|
||||
}
|
||||
|
||||
func listURL(c *gophercloud.ServiceClient) string {
|
||||
return resourceURL(c)
|
||||
}
|
||||
|
||||
func getURL(c *gophercloud.ServiceClient, id string) string {
|
||||
return c.ServiceURL(resourcePath, id)
|
||||
}
|
||||
25
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/urls_test.go
generated
vendored
Normal file
25
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks/urls_test.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
package tenantnetworks
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
func TestListURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"os-tenant-networks", listURL(c))
|
||||
}
|
||||
|
||||
func TestGetURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
id := "1"
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"os-tenant-networks/"+id, getURL(c, id))
|
||||
}
|
||||
3
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/doc.go
generated
vendored
Normal file
3
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/doc.go
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
// Package volumeattach provides the ability to attach and detach volumes
|
||||
// to instances
|
||||
package volumeattach
|
||||
138
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/fixtures.go
generated
vendored
Normal file
138
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/fixtures.go
generated
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
// +build fixtures
|
||||
|
||||
package volumeattach
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
// ListOutput is a sample response to a List call.
|
||||
const ListOutput = `
|
||||
{
|
||||
"volumeAttachments": [
|
||||
{
|
||||
"device": "/dev/vdd",
|
||||
"id": "a26887c6-c47b-4654-abb5-dfadf7d3f803",
|
||||
"serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803"
|
||||
},
|
||||
{
|
||||
"device": "/dev/vdc",
|
||||
"id": "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||
"serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
// GetOutput is a sample response to a Get call.
|
||||
const GetOutput = `
|
||||
{
|
||||
"volumeAttachment": {
|
||||
"device": "/dev/vdc",
|
||||
"id": "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||
"serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
// CreateOutput is a sample response to a Create call.
|
||||
const CreateOutput = `
|
||||
{
|
||||
"volumeAttachment": {
|
||||
"device": "/dev/vdc",
|
||||
"id": "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||
"serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
// FirstVolumeAttachment is the first result in ListOutput.
|
||||
var FirstVolumeAttachment = VolumeAttachment{
|
||||
Device: "/dev/vdd",
|
||||
ID: "a26887c6-c47b-4654-abb5-dfadf7d3f803",
|
||||
ServerID: "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||
VolumeID: "a26887c6-c47b-4654-abb5-dfadf7d3f803",
|
||||
}
|
||||
|
||||
// SecondVolumeAttachment is the first result in ListOutput.
|
||||
var SecondVolumeAttachment = VolumeAttachment{
|
||||
Device: "/dev/vdc",
|
||||
ID: "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||
ServerID: "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||
VolumeID: "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||
}
|
||||
|
||||
// ExpectedVolumeAttachmentSlide is the slice of results that should be parsed
|
||||
// from ListOutput, in the expected order.
|
||||
var ExpectedVolumeAttachmentSlice = []VolumeAttachment{FirstVolumeAttachment, SecondVolumeAttachment}
|
||||
|
||||
// CreatedVolumeAttachment is the parsed result from CreatedOutput.
|
||||
var CreatedVolumeAttachment = VolumeAttachment{
|
||||
Device: "/dev/vdc",
|
||||
ID: "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||
ServerID: "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
|
||||
VolumeID: "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||
}
|
||||
|
||||
// HandleListSuccessfully configures the test server to respond to a List request.
|
||||
func HandleListSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprintf(w, ListOutput)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleGetSuccessfully configures the test server to respond to a Get request
|
||||
// for an existing attachment
|
||||
func HandleGetSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments/a26887c6-c47b-4654-abb5-dfadf7d3f804", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "GET")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprintf(w, GetOutput)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleCreateSuccessfully configures the test server to respond to a Create request
|
||||
// for a new attachment
|
||||
func HandleCreateSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "POST")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
th.TestJSONRequest(t, r, `
|
||||
{
|
||||
"volumeAttachment": {
|
||||
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||
"device": "/dev/vdc"
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprintf(w, CreateOutput)
|
||||
})
|
||||
}
|
||||
|
||||
// HandleDeleteSuccessfully configures the test server to respond to a Delete request for a
|
||||
// an existing attachment
|
||||
func HandleDeleteSuccessfully(t *testing.T) {
|
||||
th.Mux.HandleFunc("/servers/4d8c3732-a248-40ed-bebc-539a6ffd25c0/os-volume_attachments/a26887c6-c47b-4654-abb5-dfadf7d3f804", func(w http.ResponseWriter, r *http.Request) {
|
||||
th.TestMethod(t, r, "DELETE")
|
||||
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
})
|
||||
}
|
||||
75
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/requests.go
generated
vendored
Normal file
75
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/requests.go
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
package volumeattach
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// List returns a Pager that allows you to iterate over a collection of VolumeAttachments.
|
||||
func List(client *gophercloud.ServiceClient, serverId string) pagination.Pager {
|
||||
return pagination.NewPager(client, listURL(client, serverId), func(r pagination.PageResult) pagination.Page {
|
||||
return VolumeAttachmentsPage{pagination.SinglePageBase(r)}
|
||||
})
|
||||
}
|
||||
|
||||
// CreateOptsBuilder describes struct types that can be accepted by the Create call. Notable, the
|
||||
// CreateOpts struct in this package does.
|
||||
type CreateOptsBuilder interface {
|
||||
ToVolumeAttachmentCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// CreateOpts specifies volume attachment creation or import parameters.
|
||||
type CreateOpts struct {
|
||||
// Device is the device that the volume will attach to the instance as. Omit for "auto"
|
||||
Device string
|
||||
|
||||
// VolumeID is the ID of the volume to attach to the instance
|
||||
VolumeID string
|
||||
}
|
||||
|
||||
// ToVolumeAttachmentCreateMap constructs a request body from CreateOpts.
|
||||
func (opts CreateOpts) ToVolumeAttachmentCreateMap() (map[string]interface{}, error) {
|
||||
if opts.VolumeID == "" {
|
||||
return nil, errors.New("Missing field required for volume attachment creation: VolumeID")
|
||||
}
|
||||
|
||||
volumeAttachment := make(map[string]interface{})
|
||||
volumeAttachment["volumeId"] = opts.VolumeID
|
||||
if opts.Device != "" {
|
||||
volumeAttachment["device"] = opts.Device
|
||||
}
|
||||
|
||||
return map[string]interface{}{"volumeAttachment": volumeAttachment}, nil
|
||||
}
|
||||
|
||||
// Create requests the creation of a new volume attachment on the server
|
||||
func Create(client *gophercloud.ServiceClient, serverId string, opts CreateOptsBuilder) CreateResult {
|
||||
var res CreateResult
|
||||
|
||||
reqBody, err := opts.ToVolumeAttachmentCreateMap()
|
||||
if err != nil {
|
||||
res.Err = err
|
||||
return res
|
||||
}
|
||||
|
||||
_, res.Err = client.Post(createURL(client, serverId), reqBody, &res.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
// Get returns public data about a previously created VolumeAttachment.
|
||||
func Get(client *gophercloud.ServiceClient, serverId, aId string) GetResult {
|
||||
var res GetResult
|
||||
_, res.Err = client.Get(getURL(client, serverId, aId), &res.Body, nil)
|
||||
return res
|
||||
}
|
||||
|
||||
// Delete requests the deletion of a previous stored VolumeAttachment from the server.
|
||||
func Delete(client *gophercloud.ServiceClient, serverId, aId string) DeleteResult {
|
||||
var res DeleteResult
|
||||
_, res.Err = client.Delete(deleteURL(client, serverId, aId), nil)
|
||||
return res
|
||||
}
|
||||
65
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/requests_test.go
generated
vendored
Normal file
65
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/requests_test.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
package volumeattach
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleListSuccessfully(t)
|
||||
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||
|
||||
count := 0
|
||||
err := List(client.ServiceClient(), serverId).EachPage(func(page pagination.Page) (bool, error) {
|
||||
count++
|
||||
actual, err := ExtractVolumeAttachments(page)
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckDeepEquals(t, ExpectedVolumeAttachmentSlice, actual)
|
||||
|
||||
return true, nil
|
||||
})
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckEquals(t, 1, count)
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleCreateSuccessfully(t)
|
||||
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||
|
||||
actual, err := Create(client.ServiceClient(), serverId, CreateOpts{
|
||||
Device: "/dev/vdc",
|
||||
VolumeID: "a26887c6-c47b-4654-abb5-dfadf7d3f804",
|
||||
}).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckDeepEquals(t, &CreatedVolumeAttachment, actual)
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleGetSuccessfully(t)
|
||||
aId := "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
||||
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||
|
||||
actual, err := Get(client.ServiceClient(), serverId, aId).Extract()
|
||||
th.AssertNoErr(t, err)
|
||||
th.CheckDeepEquals(t, &SecondVolumeAttachment, actual)
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
HandleDeleteSuccessfully(t)
|
||||
aId := "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
||||
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||
|
||||
err := Delete(client.ServiceClient(), serverId, aId).ExtractErr()
|
||||
th.AssertNoErr(t, err)
|
||||
}
|
||||
84
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/results.go
generated
vendored
Normal file
84
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/results.go
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
package volumeattach
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// VolumeAttach controls the attachment of a volume to an instance.
|
||||
type VolumeAttachment struct {
|
||||
// ID is a unique id of the attachment
|
||||
ID string `mapstructure:"id"`
|
||||
|
||||
// Device is what device the volume is attached as
|
||||
Device string `mapstructure:"device"`
|
||||
|
||||
// VolumeID is the ID of the attached volume
|
||||
VolumeID string `mapstructure:"volumeId"`
|
||||
|
||||
// ServerID is the ID of the instance that has the volume attached
|
||||
ServerID string `mapstructure:"serverId"`
|
||||
}
|
||||
|
||||
// VolumeAttachmentsPage stores a single, only page of VolumeAttachments
|
||||
// results from a List call.
|
||||
type VolumeAttachmentsPage struct {
|
||||
pagination.SinglePageBase
|
||||
}
|
||||
|
||||
// IsEmpty determines whether or not a VolumeAttachmentsPage is empty.
|
||||
func (page VolumeAttachmentsPage) IsEmpty() (bool, error) {
|
||||
va, err := ExtractVolumeAttachments(page)
|
||||
return len(va) == 0, err
|
||||
}
|
||||
|
||||
// ExtractVolumeAttachments interprets a page of results as a slice of
|
||||
// VolumeAttachments.
|
||||
func ExtractVolumeAttachments(page pagination.Page) ([]VolumeAttachment, error) {
|
||||
casted := page.(VolumeAttachmentsPage).Body
|
||||
var response struct {
|
||||
VolumeAttachments []VolumeAttachment `mapstructure:"volumeAttachments"`
|
||||
}
|
||||
|
||||
err := mapstructure.WeakDecode(casted, &response)
|
||||
|
||||
return response.VolumeAttachments, err
|
||||
}
|
||||
|
||||
type VolumeAttachmentResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract is a method that attempts to interpret any VolumeAttachment resource
|
||||
// response as a VolumeAttachment struct.
|
||||
func (r VolumeAttachmentResult) Extract() (*VolumeAttachment, error) {
|
||||
if r.Err != nil {
|
||||
return nil, r.Err
|
||||
}
|
||||
|
||||
var res struct {
|
||||
VolumeAttachment *VolumeAttachment `json:"volumeAttachment" mapstructure:"volumeAttachment"`
|
||||
}
|
||||
|
||||
err := mapstructure.Decode(r.Body, &res)
|
||||
return res.VolumeAttachment, err
|
||||
}
|
||||
|
||||
// CreateResult is the response from a Create operation. Call its Extract method to interpret it
|
||||
// as a VolumeAttachment.
|
||||
type CreateResult struct {
|
||||
VolumeAttachmentResult
|
||||
}
|
||||
|
||||
// GetResult is the response from a Get operation. Call its Extract method to interpret it
|
||||
// as a VolumeAttachment.
|
||||
type GetResult struct {
|
||||
VolumeAttachmentResult
|
||||
}
|
||||
|
||||
// DeleteResult is the response from a Delete operation. Call its Extract method to determine if
|
||||
// the call succeeded or failed.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
25
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/urls.go
generated
vendored
Normal file
25
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/urls.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
package volumeattach
|
||||
|
||||
import "github.com/rackspace/gophercloud"
|
||||
|
||||
const resourcePath = "os-volume_attachments"
|
||||
|
||||
func resourceURL(c *gophercloud.ServiceClient, serverId string) string {
|
||||
return c.ServiceURL("servers", serverId, resourcePath)
|
||||
}
|
||||
|
||||
func listURL(c *gophercloud.ServiceClient, serverId string) string {
|
||||
return resourceURL(c, serverId)
|
||||
}
|
||||
|
||||
func createURL(c *gophercloud.ServiceClient, serverId string) string {
|
||||
return resourceURL(c, serverId)
|
||||
}
|
||||
|
||||
func getURL(c *gophercloud.ServiceClient, serverId, aId string) string {
|
||||
return c.ServiceURL("servers", serverId, resourcePath, aId)
|
||||
}
|
||||
|
||||
func deleteURL(c *gophercloud.ServiceClient, serverId, aId string) string {
|
||||
return getURL(c, serverId, aId)
|
||||
}
|
||||
46
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/urls_test.go
generated
vendored
Normal file
46
vendor/github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/urls_test.go
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
package volumeattach
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
th "github.com/rackspace/gophercloud/testhelper"
|
||||
"github.com/rackspace/gophercloud/testhelper/client"
|
||||
)
|
||||
|
||||
func TestListURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"servers/"+serverId+"/os-volume_attachments", listURL(c, serverId))
|
||||
}
|
||||
|
||||
func TestCreateURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"servers/"+serverId+"/os-volume_attachments", createURL(c, serverId))
|
||||
}
|
||||
|
||||
func TestGetURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||
aId := "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"servers/"+serverId+"/os-volume_attachments/"+aId, getURL(c, serverId, aId))
|
||||
}
|
||||
|
||||
func TestDeleteURL(t *testing.T) {
|
||||
th.SetupHTTP()
|
||||
defer th.TeardownHTTP()
|
||||
c := client.ServiceClient()
|
||||
serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
|
||||
aId := "a26887c6-c47b-4654-abb5-dfadf7d3f804"
|
||||
|
||||
th.CheckEquals(t, c.Endpoint+"servers/"+serverId+"/os-volume_attachments/"+aId, deleteURL(c, serverId, aId))
|
||||
}
|
||||
Reference in New Issue
Block a user