Commit e6c16cd4 authored by Masahiro Sano's avatar Masahiro Sano

Update github.com/rackspace/gophercloud to HEAD

parent 6c5b3901
...@@ -235,8 +235,8 @@ ...@@ -235,8 +235,8 @@
}, },
{ {
"ImportPath": "github.com/rackspace/gophercloud", "ImportPath": "github.com/rackspace/gophercloud",
"Comment": "v1.0.0-336-g2a6e319", "Comment": "v1.0.0-490-g32d0a89",
"Rev": "2a6e3190447abe5d000f951595ead1cf98df72d8" "Rev": "32d0a893a8ef70abe76dc5153e2925b39cbea7f7"
}, },
{ {
"ImportPath": "github.com/russross/blackfriday", "ImportPath": "github.com/russross/blackfriday",
......
...@@ -10,3 +10,4 @@ Contributors ...@@ -10,3 +10,4 @@ Contributors
| Ash Wilson | <ash.wilson@rackspace.com> | Ash Wilson | <ash.wilson@rackspace.com>
| Jamie Hannaford | <jamie.hannaford@rackspace.com> | Jamie Hannaford | <jamie.hannaford@rackspace.com>
| Don Schenck | don.schenck@rackspace.com> | Don Schenck | don.schenck@rackspace.com>
| Joe Topjian | <joe@topjian.net>
// +build acceptance compute servers
package v2
import (
"os"
"testing"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/acceptance/tools"
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip"
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
th "github.com/rackspace/gophercloud/testhelper"
)
func createFIPServer(t *testing.T, client *gophercloud.ServiceClient, choices *ComputeChoices) (*servers.Server, error) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
name := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create server: %s\n", name)
pwd := tools.MakeNewPassword("")
server, err := servers.Create(client, servers.CreateOpts{
Name: name,
FlavorRef: choices.FlavorID,
ImageRef: choices.ImageID,
AdminPass: pwd,
}).Extract()
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
th.AssertEquals(t, pwd, server.AdminPass)
return server, err
}
func createFloatingIP(t *testing.T, client *gophercloud.ServiceClient) (*floatingip.FloatingIP, error) {
pool := os.Getenv("OS_POOL_NAME")
fip, err := floatingip.Create(client, &floatingip.CreateOpts{
Pool: pool,
}).Extract()
th.AssertNoErr(t, err)
t.Logf("Obtained Floating IP: %v", fip.IP)
return fip, err
}
func associateFloatingIP(t *testing.T, client *gophercloud.ServiceClient, serverId string, fip *floatingip.FloatingIP) {
err := floatingip.Associate(client, serverId, fip.IP).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Associated floating IP %v from instance %v", fip.IP, serverId)
defer func() {
err = floatingip.Disassociate(client, serverId, fip.IP).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Disassociated floating IP %v from instance %v", fip.IP, serverId)
}()
floatingIp, err := floatingip.Get(client, fip.ID).Extract()
th.AssertNoErr(t, err)
t.Logf("Floating IP %v is associated with Fixed IP %v", fip.IP, floatingIp.FixedIP)
}
func TestFloatingIP(t *testing.T) {
pool := os.Getenv("OS_POOL_NAME")
if pool == "" {
t.Fatalf("OS_POOL_NAME must be set")
}
choices, err := ComputeChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
client, err := newClient()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
server, err := createFIPServer(t, client, choices)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
defer func() {
servers.Delete(client, server.ID)
t.Logf("Server deleted.")
}()
if err = waitForStatus(client, server, "ACTIVE"); err != nil {
t.Fatalf("Unable to wait for server: %v", err)
}
fip, err := createFloatingIP(t, client)
if err != nil {
t.Fatalf("Unable to create floating IP: %v", err)
}
defer func() {
err = floatingip.Delete(client, fip.ID).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Floating IP deleted.")
}()
associateFloatingIP(t, client, server.ID, fip)
}
// +build acceptance compute servers
package v2
import (
"os"
"testing"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/acceptance/tools"
"github.com/rackspace/gophercloud/openstack"
"github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach"
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
th "github.com/rackspace/gophercloud/testhelper"
)
func newBlockClient(t *testing.T) (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
th.AssertNoErr(t, err)
client, err := openstack.AuthenticatedClient(ao)
th.AssertNoErr(t, err)
return openstack.NewBlockStorageV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
}
func createVAServer(t *testing.T, computeClient *gophercloud.ServiceClient, choices *ComputeChoices) (*servers.Server, error) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
name := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create server: %s\n", name)
pwd := tools.MakeNewPassword("")
server, err := servers.Create(computeClient, servers.CreateOpts{
Name: name,
FlavorRef: choices.FlavorID,
ImageRef: choices.ImageID,
AdminPass: pwd,
}).Extract()
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
th.AssertEquals(t, pwd, server.AdminPass)
return server, err
}
func createVAVolume(t *testing.T, blockClient *gophercloud.ServiceClient) (*volumes.Volume, error) {
volume, err := volumes.Create(blockClient, &volumes.CreateOpts{
Size: 1,
Name: "gophercloud-test-volume",
}).Extract()
th.AssertNoErr(t, err)
defer func() {
err = volumes.WaitForStatus(blockClient, volume.ID, "available", 60)
th.AssertNoErr(t, err)
}()
return volume, err
}
func createVolumeAttachment(t *testing.T, computeClient *gophercloud.ServiceClient, blockClient *gophercloud.ServiceClient, serverId string, volumeId string) {
va, err := volumeattach.Create(computeClient, serverId, &volumeattach.CreateOpts{
VolumeID: volumeId,
}).Extract()
th.AssertNoErr(t, err)
defer func() {
err = volumes.WaitForStatus(blockClient, volumeId, "in-use", 60)
th.AssertNoErr(t, err)
err = volumeattach.Delete(computeClient, serverId, va.ID).ExtractErr()
th.AssertNoErr(t, err)
err = volumes.WaitForStatus(blockClient, volumeId, "available", 60)
th.AssertNoErr(t, err)
}()
}
func TestAttachVolume(t *testing.T) {
choices, err := ComputeChoicesFromEnv()
if err != nil {
t.Fatal(err)
}
computeClient, err := newClient()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
blockClient, err := newBlockClient(t)
if err != nil {
t.Fatalf("Unable to create a blockstorage client: %v", err)
}
server, err := createVAServer(t, computeClient, choices)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
defer func() {
servers.Delete(computeClient, server.ID)
t.Logf("Server deleted.")
}()
if err = waitForStatus(computeClient, server, "ACTIVE"); err != nil {
t.Fatalf("Unable to wait for server: %v", err)
}
volume, err := createVAVolume(t, blockClient)
if err != nil {
t.Fatalf("Unable to create volume: %v", err)
}
defer func() {
err = volumes.Delete(blockClient, volume.ID).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Volume deleted.")
}()
createVolumeAttachment(t, computeClient, blockClient, server.ID, volume.ID)
}
// +build acceptance networking fwaas
package fwaas
import (
"testing"
"time"
"github.com/rackspace/gophercloud"
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls"
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies"
"github.com/rackspace/gophercloud/pagination"
th "github.com/rackspace/gophercloud/testhelper"
)
func firewallSetup(t *testing.T) string {
base.Setup(t)
return createPolicy(t, &policies.CreateOpts{})
}
func firewallTeardown(t *testing.T, policyID string) {
defer base.Teardown()
deletePolicy(t, policyID)
}
func TestFirewall(t *testing.T) {
policyID := firewallSetup(t)
defer firewallTeardown(t, policyID)
firewallID := createFirewall(t, &firewalls.CreateOpts{
Name: "gophercloud test",
Description: "acceptance test",
PolicyID: policyID,
})
waitForFirewallToBeActive(t, firewallID)
listFirewalls(t)
updateFirewall(t, firewallID, &firewalls.UpdateOpts{
Description: "acceptance test updated",
})
waitForFirewallToBeActive(t, firewallID)
deleteFirewall(t, firewallID)
waitForFirewallToBeDeleted(t, firewallID)
}
func createFirewall(t *testing.T, opts *firewalls.CreateOpts) string {
f, err := firewalls.Create(base.Client, *opts).Extract()
th.AssertNoErr(t, err)
t.Logf("Created firewall: %#v", opts)
return f.ID
}
func listFirewalls(t *testing.T) {
err := firewalls.List(base.Client, firewalls.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
firewallList, err := firewalls.ExtractFirewalls(page)
if err != nil {
t.Errorf("Failed to extract firewalls: %v", err)
return false, err
}
for _, r := range firewallList {
t.Logf("Listing firewalls: ID [%s]", r.ID)
}
return true, nil
})
th.AssertNoErr(t, err)
}
func updateFirewall(t *testing.T, firewallID string, opts *firewalls.UpdateOpts) {
f, err := firewalls.Update(base.Client, firewallID, *opts).Extract()
th.AssertNoErr(t, err)
t.Logf("Updated firewall ID [%s]", f.ID)
}
func getFirewall(t *testing.T, firewallID string) *firewalls.Firewall {
f, err := firewalls.Get(base.Client, firewallID).Extract()
th.AssertNoErr(t, err)
t.Logf("Getting firewall ID [%s]", f.ID)
return f
}
func deleteFirewall(t *testing.T, firewallID string) {
res := firewalls.Delete(base.Client, firewallID)
th.AssertNoErr(t, res.Err)
t.Logf("Deleted firewall %s", firewallID)
}
func waitForFirewallToBeActive(t *testing.T, firewallID string) {
for i := 0; i < 10; i++ {
fw := getFirewall(t, firewallID)
if fw.Status == "ACTIVE" {
break
}
time.Sleep(time.Second)
}
}
func waitForFirewallToBeDeleted(t *testing.T, firewallID string) {
for i := 0; i < 10; i++ {
err := firewalls.Get(base.Client, firewallID).Err
if err != nil {
httpStatus := err.(*gophercloud.UnexpectedResponseCodeError)
if httpStatus.Actual == 404 {
return
}
}
time.Sleep(time.Second)
}
}
// +build acceptance networking fwaas
package fwaas
import (
"testing"
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/policies"
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules"
"github.com/rackspace/gophercloud/pagination"
th "github.com/rackspace/gophercloud/testhelper"
)
func firewallPolicySetup(t *testing.T) string {
base.Setup(t)
return createRule(t, &rules.CreateOpts{
Protocol: "tcp",
Action: "allow",
})
}
func firewallPolicyTeardown(t *testing.T, ruleID string) {
defer base.Teardown()
deleteRule(t, ruleID)
}
func TestFirewallPolicy(t *testing.T) {
ruleID := firewallPolicySetup(t)
defer firewallPolicyTeardown(t, ruleID)
policyID := createPolicy(t, &policies.CreateOpts{
Name: "gophercloud test",
Description: "acceptance test",
Rules: []string{
ruleID,
},
})
listPolicies(t)
updatePolicy(t, policyID, &policies.UpdateOpts{
Description: "acceptance test updated",
})
getPolicy(t, policyID)
removeRuleFromPolicy(t, policyID, ruleID)
addRuleToPolicy(t, policyID, ruleID)
deletePolicy(t, policyID)
}
func createPolicy(t *testing.T, opts *policies.CreateOpts) string {
p, err := policies.Create(base.Client, *opts).Extract()
th.AssertNoErr(t, err)
t.Logf("Created policy: %#v", opts)
return p.ID
}
func listPolicies(t *testing.T) {
err := policies.List(base.Client, policies.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
policyList, err := policies.ExtractPolicies(page)
if err != nil {
t.Errorf("Failed to extract policies: %v", err)
return false, err
}
for _, p := range policyList {
t.Logf("Listing policies: ID [%s]", p.ID)
}
return true, nil
})
th.AssertNoErr(t, err)
}
func updatePolicy(t *testing.T, policyID string, opts *policies.UpdateOpts) {
p, err := policies.Update(base.Client, policyID, *opts).Extract()
th.AssertNoErr(t, err)
t.Logf("Updated policy ID [%s]", p.ID)
}
func removeRuleFromPolicy(t *testing.T, policyID string, ruleID string) {
err := policies.RemoveRule(base.Client, policyID, ruleID)
th.AssertNoErr(t, err)
t.Logf("Removed rule [%s] from policy ID [%s]", ruleID, policyID)
}
func addRuleToPolicy(t *testing.T, policyID string, ruleID string) {
err := policies.InsertRule(base.Client, policyID, ruleID, "", "")
th.AssertNoErr(t, err)
t.Logf("Inserted rule [%s] into policy ID [%s]", ruleID, policyID)
}
func getPolicy(t *testing.T, policyID string) {
p, err := policies.Get(base.Client, policyID).Extract()
th.AssertNoErr(t, err)
t.Logf("Getting policy ID [%s]", p.ID)
}
func deletePolicy(t *testing.T, policyID string) {
res := policies.Delete(base.Client, policyID)
th.AssertNoErr(t, res.Err)
t.Logf("Deleted policy %s", policyID)
}
// +build acceptance networking fwaas
package fwaas
import (
"testing"
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/fwaas/rules"
"github.com/rackspace/gophercloud/pagination"
th "github.com/rackspace/gophercloud/testhelper"
)
func TestFirewallRules(t *testing.T) {
base.Setup(t)
defer base.Teardown()
ruleID := createRule(t, &rules.CreateOpts{
Name: "gophercloud_test",
Description: "acceptance test",
Protocol: "tcp",
Action: "allow",
DestinationIPAddress: "192.168.0.0/24",
DestinationPort: "22",
})
listRules(t)
destinationIPAddress := "192.168.1.0/24"
destinationPort := ""
sourcePort := "1234"
updateRule(t, ruleID, &rules.UpdateOpts{
DestinationIPAddress: &destinationIPAddress,
DestinationPort: &destinationPort,
SourcePort: &sourcePort,
})
getRule(t, ruleID)
deleteRule(t, ruleID)
}
func createRule(t *testing.T, opts *rules.CreateOpts) string {
r, err := rules.Create(base.Client, *opts).Extract()
th.AssertNoErr(t, err)
t.Logf("Created rule: %#v", opts)
return r.ID
}
func listRules(t *testing.T) {
err := rules.List(base.Client, rules.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
ruleList, err := rules.ExtractRules(page)
if err != nil {
t.Errorf("Failed to extract rules: %v", err)
return false, err
}
for _, r := range ruleList {
t.Logf("Listing rules: ID [%s]", r.ID)
}
return true, nil
})
th.AssertNoErr(t, err)
}
func updateRule(t *testing.T, ruleID string, opts *rules.UpdateOpts) {
r, err := rules.Update(base.Client, ruleID, *opts).Extract()
th.AssertNoErr(t, err)
t.Logf("Updated rule ID [%s]", r.ID)
}
func getRule(t *testing.T, ruleID string) {
r, err := rules.Get(base.Client, ruleID).Extract()
th.AssertNoErr(t, err)
t.Logf("Getting rule ID [%s]", r.ID)
}
func deleteRule(t *testing.T, ruleID string) {
res := rules.Delete(base.Client, ruleID)
th.AssertNoErr(t, res.Err)
t.Logf("Deleted rule %s", ruleID)
}
...@@ -87,3 +87,51 @@ func TestContainers(t *testing.T) { ...@@ -87,3 +87,51 @@ func TestContainers(t *testing.T) {
} }
} }
} }
func TestListAllContainers(t *testing.T) {
// Create a new client to execute the HTTP requests. See common.go for newClient body.
client := newClient(t)
numContainers := 20
// Create a slice of random container names.
cNames := make([]string, numContainers)
for i := 0; i < numContainers; i++ {
cNames[i] = tools.RandomString("gophercloud-test-container-", 8)
}
// Create numContainers containers.
for i := 0; i < len(cNames); i++ {
res := containers.Create(client, cNames[i], nil)
th.AssertNoErr(t, res.Err)
}
// Delete the numContainers containers after function completion.
defer func() {
for i := 0; i < len(cNames); i++ {
res := containers.Delete(client, cNames[i])
th.AssertNoErr(t, res.Err)
}
}()
// List all the numContainer names that were just created. To just list those,
// the 'prefix' parameter is used.
allPages, err := containers.List(client, &containers.ListOpts{Full: true, Limit: 5, Prefix: "gophercloud-test-container-"}).AllPages()
th.AssertNoErr(t, err)
containerInfoList, err := containers.ExtractInfo(allPages)
th.AssertNoErr(t, err)
for _, n := range containerInfoList {
t.Logf("Container: Name [%s] Count [%d] Bytes [%d]",
n.Name, n.Count, n.Bytes)
}
th.AssertEquals(t, numContainers, len(containerInfoList))
// List the info for all the numContainer containers that were created.
allPages, err = containers.List(client, &containers.ListOpts{Full: false, Limit: 2, Prefix: "gophercloud-test-container-"}).AllPages()
th.AssertNoErr(t, err)
containerNamesList, err := containers.ExtractNames(allPages)
th.AssertNoErr(t, err)
for _, n := range containerNamesList {
t.Logf("Container: Name [%s]", n)
}
th.AssertEquals(t, numContainers, len(containerNamesList))
}
// +build acceptance
package v1
import (
"testing"
"github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo"
th "github.com/rackspace/gophercloud/testhelper"
)
func TestBuildInfo(t *testing.T) {
// Create a provider client for making the HTTP requests.
// See common.go in this directory for more information.
client := newClient(t)
bi, err := buildinfo.Get(client).Extract()
th.AssertNoErr(t, err)
t.Logf("retrieved build info: %+v\n", bi)
}
// +build acceptance
package v1
import (
"fmt"
"os"
"testing"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack"
th "github.com/rackspace/gophercloud/testhelper"
)
var template = fmt.Sprintf(`
{
"heat_template_version": "2013-05-23",
"description": "Simple template to test heat commands",
"parameters": {},
"resources": {
"hello_world": {
"type":"OS::Nova::Server",
"properties": {
"flavor": "%s",
"image": "%s",
"user_data": "#!/bin/bash -xv\necho \"hello world\" &gt; /root/hello-world.txt\n"
}
}
}
}`, os.Getenv("OS_FLAVOR_ID"), os.Getenv("OS_IMAGE_ID"))
func newClient(t *testing.T) *gophercloud.ServiceClient {
ao, err := openstack.AuthOptionsFromEnv()
th.AssertNoErr(t, err)
client, err := openstack.AuthenticatedClient(ao)
th.AssertNoErr(t, err)
c, err := openstack.NewOrchestrationV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
th.AssertNoErr(t, err)
return c
}
{
"heat_template_version": "2013-05-23",
"resources": {
"compute_instance": {
"type": "OS::Nova::Server",
"properties": {
"flavor": "m1.small",
"image": "cirros-0.3.2-x86_64-disk",
"name": "Single Compute Instance"
}
}
}
}
// +build acceptance
package v1
import (
"testing"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents"
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
"github.com/rackspace/gophercloud/pagination"
th "github.com/rackspace/gophercloud/testhelper"
)
func TestStackEvents(t *testing.T) {
// Create a provider client for making the HTTP requests.
// See common.go in this directory for more information.
client := newClient(t)
stackName := "postman_stack_2"
resourceName := "hello_world"
var eventID string
createOpts := stacks.CreateOpts{
Name: stackName,
Template: template,
Timeout: 5,
}
stack, err := stacks.Create(client, createOpts).Extract()
th.AssertNoErr(t, err)
t.Logf("Created stack: %+v\n", stack)
defer func() {
err := stacks.Delete(client, stackName, stack.ID).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Deleted stack (%s)", stackName)
}()
err = gophercloud.WaitFor(60, func() (bool, error) {
getStack, err := stacks.Get(client, stackName, stack.ID).Extract()
if err != nil {
return false, err
}
if getStack.Status == "CREATE_COMPLETE" {
return true, nil
}
return false, nil
})
err = stackevents.List(client, stackName, stack.ID, nil).EachPage(func(page pagination.Page) (bool, error) {
events, err := stackevents.ExtractEvents(page)
th.AssertNoErr(t, err)
t.Logf("listed events: %+v\n", events)
eventID = events[0].ID
return false, nil
})
th.AssertNoErr(t, err)
err = stackevents.ListResourceEvents(client, stackName, stack.ID, resourceName, nil).EachPage(func(page pagination.Page) (bool, error) {
resourceEvents, err := stackevents.ExtractEvents(page)
th.AssertNoErr(t, err)
t.Logf("listed resource events: %+v\n", resourceEvents)
return false, nil
})
th.AssertNoErr(t, err)
event, err := stackevents.Get(client, stackName, stack.ID, resourceName, eventID).Extract()
th.AssertNoErr(t, err)
t.Logf("retrieved event: %+v\n", event)
}
// +build acceptance
package v1
import (
"testing"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources"
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
"github.com/rackspace/gophercloud/pagination"
th "github.com/rackspace/gophercloud/testhelper"
)
func TestStackResources(t *testing.T) {
// Create a provider client for making the HTTP requests.
// See common.go in this directory for more information.
client := newClient(t)
stackName := "postman_stack_2"
createOpts := stacks.CreateOpts{
Name: stackName,
Template: template,
Timeout: 5,
}
stack, err := stacks.Create(client, createOpts).Extract()
th.AssertNoErr(t, err)
t.Logf("Created stack: %+v\n", stack)
defer func() {
err := stacks.Delete(client, stackName, stack.ID).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Deleted stack (%s)", stackName)
}()
err = gophercloud.WaitFor(60, func() (bool, error) {
getStack, err := stacks.Get(client, stackName, stack.ID).Extract()
if err != nil {
return false, err
}
if getStack.Status == "CREATE_COMPLETE" {
return true, nil
}
return false, nil
})
resourceName := "hello_world"
resource, err := stackresources.Get(client, stackName, stack.ID, resourceName).Extract()
th.AssertNoErr(t, err)
t.Logf("Got stack resource: %+v\n", resource)
metadata, err := stackresources.Metadata(client, stackName, stack.ID, resourceName).Extract()
th.AssertNoErr(t, err)
t.Logf("Got stack resource metadata: %+v\n", metadata)
err = stackresources.List(client, stackName, stack.ID, stackresources.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
resources, err := stackresources.ExtractResources(page)
th.AssertNoErr(t, err)
t.Logf("resources: %+v\n", resources)
return false, nil
})
th.AssertNoErr(t, err)
}
// +build acceptance
package v1
import (
"testing"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
"github.com/rackspace/gophercloud/pagination"
th "github.com/rackspace/gophercloud/testhelper"
)
func TestStacks(t *testing.T) {
// Create a provider client for making the HTTP requests.
// See common.go in this directory for more information.
client := newClient(t)
stackName1 := "gophercloud-test-stack-2"
createOpts := stacks.CreateOpts{
Name: stackName1,
Template: template,
Timeout: 5,
}
stack, err := stacks.Create(client, createOpts).Extract()
th.AssertNoErr(t, err)
t.Logf("Created stack: %+v\n", stack)
defer func() {
err := stacks.Delete(client, stackName1, stack.ID).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Deleted stack (%s)", stackName1)
}()
err = gophercloud.WaitFor(60, func() (bool, error) {
getStack, err := stacks.Get(client, stackName1, stack.ID).Extract()
if err != nil {
return false, err
}
if getStack.Status == "CREATE_COMPLETE" {
return true, nil
}
return false, nil
})
updateOpts := stacks.UpdateOpts{
Template: template,
Timeout: 20,
}
err = stacks.Update(client, stackName1, stack.ID, updateOpts).ExtractErr()
th.AssertNoErr(t, err)
err = gophercloud.WaitFor(60, func() (bool, error) {
getStack, err := stacks.Get(client, stackName1, stack.ID).Extract()
if err != nil {
return false, err
}
if getStack.Status == "UPDATE_COMPLETE" {
return true, nil
}
return false, nil
})
t.Logf("Updated stack")
err = stacks.List(client, nil).EachPage(func(page pagination.Page) (bool, error) {
stackList, err := stacks.ExtractStacks(page)
th.AssertNoErr(t, err)
t.Logf("Got stack list: %+v\n", stackList)
return true, nil
})
th.AssertNoErr(t, err)
getStack, err := stacks.Get(client, stackName1, stack.ID).Extract()
th.AssertNoErr(t, err)
t.Logf("Got stack: %+v\n", getStack)
abandonedStack, err := stacks.Abandon(client, stackName1, stack.ID).Extract()
th.AssertNoErr(t, err)
t.Logf("Abandonded stack %+v\n", abandonedStack)
th.AssertNoErr(t, err)
}
// +build acceptance
package v1
import (
"testing"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
"github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates"
th "github.com/rackspace/gophercloud/testhelper"
)
func TestStackTemplates(t *testing.T) {
// Create a provider client for making the HTTP requests.
// See common.go in this directory for more information.
client := newClient(t)
stackName := "postman_stack_2"
createOpts := stacks.CreateOpts{
Name: stackName,
Template: template,
Timeout: 5,
}
stack, err := stacks.Create(client, createOpts).Extract()
th.AssertNoErr(t, err)
t.Logf("Created stack: %+v\n", stack)
defer func() {
err := stacks.Delete(client, stackName, stack.ID).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Deleted stack (%s)", stackName)
}()
err = gophercloud.WaitFor(60, func() (bool, error) {
getStack, err := stacks.Get(client, stackName, stack.ID).Extract()
if err != nil {
return false, err
}
if getStack.Status == "CREATE_COMPLETE" {
return true, nil
}
return false, nil
})
tmpl, err := stacktemplates.Get(client, stackName, stack.ID).Extract()
th.AssertNoErr(t, err)
t.Logf("retrieved template: %+v\n", tmpl)
validateOpts := stacktemplates.ValidateOpts{
Template: map[string]interface{}{
"heat_template_version": "2013-05-23",
"description": "Simple template to test heat commands",
"parameters": map[string]interface{}{
"flavor": map[string]interface{}{
"default": "m1.tiny",
"type": "string",
},
},
"resources": map[string]interface{}{
"hello_world": map[string]interface{}{
"type": "OS::Nova::Server",
"properties": map[string]interface{}{
"key_name": "heat_key",
"flavor": map[string]interface{}{
"get_param": "flavor",
},
"image": "ad091b52-742f-469e-8f3c-fd81cadf0743",
"user_data": "#!/bin/bash -xv\necho \"hello world\" &gt; /root/hello-world.txt\n",
},
},
},
},
}
validatedTemplate, err := stacktemplates.Validate(client, validateOpts).Extract()
th.AssertNoErr(t, err)
t.Logf("validated template: %+v\n", validatedTemplate)
}
// +build acceptance compute servers
package v2
import (
"os"
"testing"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/acceptance/tools"
"github.com/rackspace/gophercloud/openstack"
osVolumes "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
osVolumeAttach "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach"
osServers "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
"github.com/rackspace/gophercloud/rackspace"
"github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes"
"github.com/rackspace/gophercloud/rackspace/compute/v2/servers"
"github.com/rackspace/gophercloud/rackspace/compute/v2/volumeattach"
th "github.com/rackspace/gophercloud/testhelper"
)
func newBlockClient(t *testing.T) (*gophercloud.ServiceClient, error) {
ao, err := rackspace.AuthOptionsFromEnv()
th.AssertNoErr(t, err)
client, err := rackspace.AuthenticatedClient(ao)
th.AssertNoErr(t, err)
return openstack.NewBlockStorageV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("RS_REGION_NAME"),
})
}
func createVAServer(t *testing.T, computeClient *gophercloud.ServiceClient, choices *serverOpts) (*osServers.Server, error) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
name := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create server: %s\n", name)
pwd := tools.MakeNewPassword("")
server, err := servers.Create(computeClient, osServers.CreateOpts{
Name: name,
FlavorRef: choices.flavorID,
ImageRef: choices.imageID,
AdminPass: pwd,
}).Extract()
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
th.AssertEquals(t, pwd, server.AdminPass)
return server, err
}
func createVAVolume(t *testing.T, blockClient *gophercloud.ServiceClient) (*volumes.Volume, error) {
volume, err := volumes.Create(blockClient, &osVolumes.CreateOpts{
Size: 80,
Name: "gophercloud-test-volume",
}).Extract()
th.AssertNoErr(t, err)
defer func() {
err = osVolumes.WaitForStatus(blockClient, volume.ID, "available", 60)
th.AssertNoErr(t, err)
}()
return volume, err
}
func createVolumeAttachment(t *testing.T, computeClient *gophercloud.ServiceClient, blockClient *gophercloud.ServiceClient, serverID string, volumeID string) {
va, err := volumeattach.Create(computeClient, serverID, &osVolumeAttach.CreateOpts{
VolumeID: volumeID,
}).Extract()
th.AssertNoErr(t, err)
defer func() {
err = osVolumes.WaitForStatus(blockClient, volumeID, "in-use", 60)
th.AssertNoErr(t, err)
err = volumeattach.Delete(computeClient, serverID, va.ID).ExtractErr()
th.AssertNoErr(t, err)
err = osVolumes.WaitForStatus(blockClient, volumeID, "available", 60)
th.AssertNoErr(t, err)
}()
t.Logf("Attached volume to server: %+v", va)
}
func TestAttachVolume(t *testing.T) {
choices, err := optionsFromEnv()
if err != nil {
t.Fatal(err)
}
computeClient, err := newClient()
if err != nil {
t.Fatalf("Unable to create a compute client: %v", err)
}
blockClient, err := newBlockClient(t)
if err != nil {
t.Fatalf("Unable to create a blockstorage client: %v", err)
}
server, err := createVAServer(t, computeClient, choices)
if err != nil {
t.Fatalf("Unable to create server: %v", err)
}
defer func() {
servers.Delete(computeClient, server.ID)
t.Logf("Server deleted.")
}()
if err = osServers.WaitForStatus(computeClient, server.ID, "ACTIVE", 300); err != nil {
t.Fatalf("Unable to wait for server: %v", err)
}
volume, err := createVAVolume(t, blockClient)
if err != nil {
t.Fatalf("Unable to create volume: %v", err)
}
defer func() {
err = volumes.Delete(blockClient, volume.ID).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Volume deleted.")
}()
createVolumeAttachment(t, computeClient, blockClient, server.ID, volume.ID)
}
...@@ -36,11 +36,15 @@ func TestCDNObjects(t *testing.T) { ...@@ -36,11 +36,15 @@ func TestCDNObjects(t *testing.T) {
raxCDNClient, err := createClient(t, true) raxCDNClient, err := createClient(t, true)
th.AssertNoErr(t, err) th.AssertNoErr(t, err)
enableResult := raxCDNContainers.Enable(raxCDNClient, "gophercloud-test", raxCDNContainers.EnableOpts{CDNEnabled: true, TTL: 900}) enableHeader, err := raxCDNContainers.Enable(raxCDNClient, "gophercloud-test", raxCDNContainers.EnableOpts{CDNEnabled: true, TTL: 900}).Extract()
th.AssertNoErr(t, enableResult.Err) th.AssertNoErr(t, err)
t.Logf("Headers from Enable CDN Container request: %+v\n", enableResult.Header) t.Logf("Headers from Enable CDN Container request: %+v\n", enableHeader)
objCDNURL, err := raxCDNObjects.CDNURL(raxCDNClient, "gophercloud-test", "test-object")
th.AssertNoErr(t, err)
t.Logf("%s CDN URL: %s\n", "test_object", objCDNURL)
deleteResult := raxCDNObjects.Delete(raxCDNClient, "gophercloud-test", "test-object", nil) deleteHeader, err := raxCDNObjects.Delete(raxCDNClient, "gophercloud-test", "test-object", nil).Extract()
th.AssertNoErr(t, deleteResult.Err) th.AssertNoErr(t, err)
t.Logf("Headers from Delete CDN Object request: %+v\n", deleteResult.Err) t.Logf("Headers from Delete CDN Object request: %+v\n", deleteHeader)
} }
// +build acceptance
package v1
import (
"testing"
"github.com/rackspace/gophercloud/rackspace/orchestration/v1/buildinfo"
th "github.com/rackspace/gophercloud/testhelper"
)
func TestBuildInfo(t *testing.T) {
// Create a provider client for making the HTTP requests.
// See common.go in this directory for more information.
client := newClient(t)
bi, err := buildinfo.Get(client).Extract()
th.AssertNoErr(t, err)
t.Logf("retrieved build info: %+v\n", bi)
}
// +build acceptance
package v1
import (
"fmt"
"os"
"testing"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/rackspace"
th "github.com/rackspace/gophercloud/testhelper"
)
var template = fmt.Sprintf(`
{
"heat_template_version": "2013-05-23",
"description": "Simple template to test heat commands",
"parameters": {},
"resources": {
"hello_world": {
"type":"OS::Nova::Server",
"properties": {
"flavor": "%s",
"image": "%s",
"user_data": "#!/bin/bash -xv\necho \"hello world\" &gt; /root/hello-world.txt\n"
}
}
}
}
`, os.Getenv("RS_FLAVOR_ID"), os.Getenv("RS_IMAGE_ID"))
func newClient(t *testing.T) *gophercloud.ServiceClient {
ao, err := rackspace.AuthOptionsFromEnv()
th.AssertNoErr(t, err)
client, err := rackspace.AuthenticatedClient(ao)
th.AssertNoErr(t, err)
c, err := rackspace.NewOrchestrationV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("RS_REGION_NAME"),
})
th.AssertNoErr(t, err)
return c
}
// +build acceptance
package v1
import (
"testing"
"github.com/rackspace/gophercloud"
osStackEvents "github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents"
osStacks "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
"github.com/rackspace/gophercloud/pagination"
"github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackevents"
"github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks"
th "github.com/rackspace/gophercloud/testhelper"
)
func TestStackEvents(t *testing.T) {
// Create a provider client for making the HTTP requests.
// See common.go in this directory for more information.
client := newClient(t)
stackName := "postman_stack_2"
resourceName := "hello_world"
var eventID string
createOpts := osStacks.CreateOpts{
Name: stackName,
Template: template,
Timeout: 5,
}
stack, err := stacks.Create(client, createOpts).Extract()
th.AssertNoErr(t, err)
t.Logf("Created stack: %+v\n", stack)
defer func() {
err := stacks.Delete(client, stackName, stack.ID).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Deleted stack (%s)", stackName)
}()
err = gophercloud.WaitFor(60, func() (bool, error) {
getStack, err := stacks.Get(client, stackName, stack.ID).Extract()
if err != nil {
return false, err
}
if getStack.Status == "CREATE_COMPLETE" {
return true, nil
}
return false, nil
})
err = stackevents.List(client, stackName, stack.ID, nil).EachPage(func(page pagination.Page) (bool, error) {
events, err := osStackEvents.ExtractEvents(page)
th.AssertNoErr(t, err)
t.Logf("listed events: %+v\n", events)
eventID = events[0].ID
return false, nil
})
th.AssertNoErr(t, err)
err = stackevents.ListResourceEvents(client, stackName, stack.ID, resourceName, nil).EachPage(func(page pagination.Page) (bool, error) {
resourceEvents, err := osStackEvents.ExtractResourceEvents(page)
th.AssertNoErr(t, err)
t.Logf("listed resource events: %+v\n", resourceEvents)
return false, nil
})
th.AssertNoErr(t, err)
event, err := stackevents.Get(client, stackName, stack.ID, resourceName, eventID).Extract()
th.AssertNoErr(t, err)
t.Logf("retrieved event: %+v\n", event)
}
// +build acceptance
package v1
import (
"testing"
"github.com/rackspace/gophercloud"
osStackResources "github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources"
osStacks "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
"github.com/rackspace/gophercloud/pagination"
"github.com/rackspace/gophercloud/rackspace/orchestration/v1/stackresources"
"github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks"
th "github.com/rackspace/gophercloud/testhelper"
)
func TestStackResources(t *testing.T) {
// Create a provider client for making the HTTP requests.
// See common.go in this directory for more information.
client := newClient(t)
stackName := "postman_stack_2"
createOpts := osStacks.CreateOpts{
Name: stackName,
Template: template,
Timeout: 5,
}
stack, err := stacks.Create(client, createOpts).Extract()
th.AssertNoErr(t, err)
t.Logf("Created stack: %+v\n", stack)
defer func() {
err := stacks.Delete(client, stackName, stack.ID).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Deleted stack (%s)", stackName)
}()
err = gophercloud.WaitFor(60, func() (bool, error) {
getStack, err := stacks.Get(client, stackName, stack.ID).Extract()
if err != nil {
return false, err
}
if getStack.Status == "CREATE_COMPLETE" {
return true, nil
}
return false, nil
})
resourceName := "hello_world"
resource, err := stackresources.Get(client, stackName, stack.ID, resourceName).Extract()
th.AssertNoErr(t, err)
t.Logf("Got stack resource: %+v\n", resource)
metadata, err := stackresources.Metadata(client, stackName, stack.ID, resourceName).Extract()
th.AssertNoErr(t, err)
t.Logf("Got stack resource metadata: %+v\n", metadata)
err = stackresources.List(client, stackName, stack.ID, nil).EachPage(func(page pagination.Page) (bool, error) {
resources, err := osStackResources.ExtractResources(page)
th.AssertNoErr(t, err)
t.Logf("resources: %+v\n", resources)
return false, nil
})
th.AssertNoErr(t, err)
}
// +build acceptance
package v1
import (
"testing"
"github.com/rackspace/gophercloud"
osStacks "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
"github.com/rackspace/gophercloud/pagination"
"github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks"
th "github.com/rackspace/gophercloud/testhelper"
)
func TestStacks(t *testing.T) {
// Create a provider client for making the HTTP requests.
// See common.go in this directory for more information.
client := newClient(t)
stackName1 := "gophercloud-test-stack-2"
createOpts := osStacks.CreateOpts{
Name: stackName1,
Template: template,
Timeout: 5,
}
stack, err := stacks.Create(client, createOpts).Extract()
th.AssertNoErr(t, err)
t.Logf("Created stack: %+v\n", stack)
defer func() {
err := stacks.Delete(client, stackName1, stack.ID).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Deleted stack (%s)", stackName1)
}()
err = gophercloud.WaitFor(60, func() (bool, error) {
getStack, err := stacks.Get(client, stackName1, stack.ID).Extract()
if err != nil {
return false, err
}
if getStack.Status == "CREATE_COMPLETE" {
return true, nil
}
return false, nil
})
updateOpts := osStacks.UpdateOpts{
Template: template,
Timeout: 20,
}
err = stacks.Update(client, stackName1, stack.ID, updateOpts).ExtractErr()
th.AssertNoErr(t, err)
err = gophercloud.WaitFor(60, func() (bool, error) {
getStack, err := stacks.Get(client, stackName1, stack.ID).Extract()
if err != nil {
return false, err
}
if getStack.Status == "UPDATE_COMPLETE" {
return true, nil
}
return false, nil
})
t.Logf("Updated stack")
err = stacks.List(client, nil).EachPage(func(page pagination.Page) (bool, error) {
stackList, err := osStacks.ExtractStacks(page)
th.AssertNoErr(t, err)
t.Logf("Got stack list: %+v\n", stackList)
return true, nil
})
th.AssertNoErr(t, err)
getStack, err := stacks.Get(client, stackName1, stack.ID).Extract()
th.AssertNoErr(t, err)
t.Logf("Got stack: %+v\n", getStack)
abandonedStack, err := stacks.Abandon(client, stackName1, stack.ID).Extract()
th.AssertNoErr(t, err)
t.Logf("Abandonded stack %+v\n", abandonedStack)
th.AssertNoErr(t, err)
}
// +build acceptance
package v1
import (
"testing"
"github.com/rackspace/gophercloud"
osStacks "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
osStacktemplates "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates"
"github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacks"
"github.com/rackspace/gophercloud/rackspace/orchestration/v1/stacktemplates"
th "github.com/rackspace/gophercloud/testhelper"
)
func TestStackTemplates(t *testing.T) {
// Create a provider client for making the HTTP requests.
// See common.go in this directory for more information.
client := newClient(t)
stackName := "postman_stack_2"
createOpts := osStacks.CreateOpts{
Name: stackName,
Template: template,
Timeout: 5,
}
stack, err := stacks.Create(client, createOpts).Extract()
th.AssertNoErr(t, err)
t.Logf("Created stack: %+v\n", stack)
defer func() {
err := stacks.Delete(client, stackName, stack.ID).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Deleted stack (%s)", stackName)
}()
err = gophercloud.WaitFor(60, func() (bool, error) {
getStack, err := stacks.Get(client, stackName, stack.ID).Extract()
if err != nil {
return false, err
}
if getStack.Status == "CREATE_COMPLETE" {
return true, nil
}
return false, nil
})
tmpl, err := stacktemplates.Get(client, stackName, stack.ID).Extract()
th.AssertNoErr(t, err)
t.Logf("retrieved template: %+v\n", tmpl)
validateOpts := osStacktemplates.ValidateOpts{
Template: map[string]interface{}{
"heat_template_version": "2013-05-23",
"description": "Simple template to test heat commands",
"parameters": map[string]interface{}{
"flavor": map[string]interface{}{
"default": "m1.tiny",
"type": "string",
},
},
"resources": map[string]interface{}{
"hello_world": map[string]interface{}{
"type": "OS::Nova::Server",
"properties": map[string]interface{}{
"key_name": "heat_key",
"flavor": map[string]interface{}{
"get_param": "flavor",
},
"image": "ad091b52-742f-469e-8f3c-fd81cadf0743",
"user_data": "#!/bin/bash -xv\necho \"hello world\" &gt; /root/hello-world.txt\n",
},
},
},
},
}
validatedTemplate, err := stacktemplates.Validate(client, validateOpts).Extract()
th.AssertNoErr(t, err)
t.Logf("validated template: %+v\n", validatedTemplate)
}
...@@ -42,7 +42,5 @@ type AuthOptions struct { ...@@ -42,7 +42,5 @@ type AuthOptions struct {
// re-authenticate automatically if/when your token expires. If you set it to // re-authenticate automatically if/when your token expires. If you set it to
// false, it will not cache these settings, but re-authentication will not be // false, it will not cache these settings, but re-authentication will not be
// possible. This setting defaults to false. // possible. This setting defaults to false.
//
// This setting is speculative and is currently not respected!
AllowReauth bool AllowReauth bool
} }
...@@ -3,8 +3,6 @@ package apiversions ...@@ -3,8 +3,6 @@ package apiversions
import ( import (
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
"github.com/racker/perigee"
) )
// List lists all the Cinder API versions available to end-users. // List lists all the Cinder API versions available to end-users.
...@@ -18,11 +16,9 @@ func List(c *gophercloud.ServiceClient) pagination.Pager { ...@@ -18,11 +16,9 @@ func List(c *gophercloud.ServiceClient) pagination.Pager {
// type from the result, call the Extract method on the GetResult. // type from the result, call the Extract method on the GetResult.
func Get(client *gophercloud.ServiceClient, v string) GetResult { func Get(client *gophercloud.ServiceClient, v string) GetResult {
var res GetResult var res GetResult
_, err := perigee.Request("GET", getURL(client, v), perigee.Options{ _, res.Err = client.Request("GET", getURL(client, v), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200},
OkCodes: []int{200}, JSONResponse: &res.Body,
Results: &res.Body,
}) })
res.Err = err
return res return res
} }
...@@ -5,8 +5,6 @@ import ( ...@@ -5,8 +5,6 @@ import (
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
"github.com/racker/perigee"
) )
// CreateOptsBuilder allows extensions to add additional parameters to the // CreateOptsBuilder allows extensions to add additional parameters to the
...@@ -69,11 +67,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes ...@@ -69,11 +67,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
return res return res
} }
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{ _, res.Err = client.Request("POST", createURL(client), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200, 201},
OkCodes: []int{200, 201}, JSONBody: &reqBody,
ReqBody: &reqBody, JSONResponse: &res.Body,
Results: &res.Body,
}) })
return res return res
} }
...@@ -81,9 +78,8 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes ...@@ -81,9 +78,8 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
// Delete will delete the existing Snapshot with the provided ID. // Delete will delete the existing Snapshot with the provided ID.
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
var res DeleteResult var res DeleteResult
_, res.Err = perigee.Request("DELETE", deleteURL(client, id), perigee.Options{ _, res.Err = client.Request("DELETE", deleteURL(client, id), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{202, 204},
OkCodes: []int{202, 204},
}) })
return res return res
} }
...@@ -92,10 +88,9 @@ func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { ...@@ -92,10 +88,9 @@ func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
// object from the response, call the Extract method on the GetResult. // object from the response, call the Extract method on the GetResult.
func Get(client *gophercloud.ServiceClient, id string) GetResult { func Get(client *gophercloud.ServiceClient, id string) GetResult {
var res GetResult var res GetResult
_, res.Err = perigee.Request("GET", getURL(client, id), perigee.Options{ _, res.Err = client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
Results: &res.Body, OkCodes: []int{200},
MoreHeaders: client.AuthenticatedHeaders(), JSONResponse: &res.Body,
OkCodes: []int{200},
}) })
return res return res
} }
...@@ -178,11 +173,10 @@ func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMet ...@@ -178,11 +173,10 @@ func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMet
return res return res
} }
_, res.Err = perigee.Request("PUT", updateMetadataURL(client, id), perigee.Options{ _, res.Err = client.Request("PUT", updateMetadataURL(client, id), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200},
OkCodes: []int{200}, JSONBody: &reqBody,
ReqBody: &reqBody, JSONResponse: &res.Body,
Results: &res.Body,
}) })
return res return res
} }
...@@ -45,8 +45,16 @@ func MockGetResponse(t *testing.T) { ...@@ -45,8 +45,16 @@ func MockGetResponse(t *testing.T) {
{ {
"volume": { "volume": {
"display_name": "vol-001", "display_name": "vol-001",
"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22" "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22",
} "attachments": [
{
"device": "/dev/vde",
"server_id": "a740d24b-dc5b-4d59-ac75-53971c2920ba",
"id": "d6da11e5-2ed3-413e-88d8-b772ba62193d",
"volume_id": "d6da11e5-2ed3-413e-88d8-b772ba62193d"
}
]
}
} }
`) `)
}) })
......
...@@ -5,8 +5,6 @@ import ( ...@@ -5,8 +5,6 @@ import (
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
"github.com/racker/perigee"
) )
// CreateOptsBuilder allows extensions to add additional parameters to the // CreateOptsBuilder allows extensions to add additional parameters to the
...@@ -85,11 +83,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes ...@@ -85,11 +83,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
return res return res
} }
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{ _, res.Err = client.Request("POST", createURL(client), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200, 201},
ReqBody: &reqBody, JSONBody: &reqBody,
Results: &res.Body, JSONResponse: &res.Body,
OkCodes: []int{200, 201},
}) })
return res return res
} }
...@@ -97,9 +94,8 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes ...@@ -97,9 +94,8 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
// Delete will delete the existing Volume with the provided ID. // Delete will delete the existing Volume with the provided ID.
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
var res DeleteResult var res DeleteResult
_, res.Err = perigee.Request("DELETE", deleteURL(client, id), perigee.Options{ _, res.Err = client.Request("DELETE", deleteURL(client, id), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{202, 204},
OkCodes: []int{202, 204},
}) })
return res return res
} }
...@@ -108,10 +104,9 @@ func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { ...@@ -108,10 +104,9 @@ func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
// from the response, call the Extract method on the GetResult. // from the response, call the Extract method on the GetResult.
func Get(client *gophercloud.ServiceClient, id string) GetResult { func Get(client *gophercloud.ServiceClient, id string) GetResult {
var res GetResult var res GetResult
_, res.Err = perigee.Request("GET", getURL(client, id), perigee.Options{ _, res.Err = client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
Results: &res.Body, JSONResponse: &res.Body,
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200},
OkCodes: []int{200},
}) })
return res return res
} }
...@@ -157,6 +152,7 @@ func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pa ...@@ -157,6 +152,7 @@ func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pa
createPage := func(r pagination.PageResult) pagination.Page { createPage := func(r pagination.PageResult) pagination.Page {
return ListResult{pagination.SinglePageBase(r)} return ListResult{pagination.SinglePageBase(r)}
} }
return pagination.NewPager(client, url, createPage) return pagination.NewPager(client, url, createPage)
} }
...@@ -207,11 +203,10 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder ...@@ -207,11 +203,10 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
return res return res
} }
_, res.Err = perigee.Request("PUT", updateURL(client, id), perigee.Options{ _, res.Err = client.Request("PUT", updateURL(client, id), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200},
OkCodes: []int{200}, JSONBody: &reqBody,
ReqBody: &reqBody, JSONResponse: &res.Body,
Results: &res.Body,
}) })
return res return res
} }
...@@ -45,6 +45,32 @@ func TestList(t *testing.T) { ...@@ -45,6 +45,32 @@ func TestList(t *testing.T) {
} }
} }
func TestListAll(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
MockListResponse(t)
allPages, err := List(client.ServiceClient(), &ListOpts{}).AllPages()
th.AssertNoErr(t, err)
actual, err := ExtractVolumes(allPages)
th.AssertNoErr(t, err)
expected := []Volume{
Volume{
ID: "289da7f8-6440-407c-9fb4-7db01ec49164",
Name: "vol-001",
},
Volume{
ID: "96c3bda7-c82a-4f50-be73-ca7621794835",
Name: "vol-002",
},
}
th.CheckDeepEquals(t, expected, actual)
}
func TestGet(t *testing.T) { func TestGet(t *testing.T) {
th.SetupHTTP() th.SetupHTTP()
defer th.TeardownHTTP() defer th.TeardownHTTP()
...@@ -56,6 +82,7 @@ func TestGet(t *testing.T) { ...@@ -56,6 +82,7 @@ func TestGet(t *testing.T) {
th.AssertEquals(t, v.Name, "vol-001") th.AssertEquals(t, v.Name, "vol-001")
th.AssertEquals(t, v.ID, "d32019d3-bc6e-4319-9c1d-6722fc136a22") th.AssertEquals(t, v.ID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
th.AssertEquals(t, v.Attachments[0]["device"], "/dev/vde")
} }
func TestCreate(t *testing.T) { func TestCreate(t *testing.T) {
......
...@@ -16,7 +16,7 @@ type Volume struct { ...@@ -16,7 +16,7 @@ type Volume struct {
Name string `mapstructure:"display_name"` Name string `mapstructure:"display_name"`
// Instances onto which the volume is attached. // Instances onto which the volume is attached.
Attachments []string `mapstructure:"attachments"` Attachments []map[string]interface{} `mapstructure:"attachments"`
// This parameter is no longer used. // This parameter is no longer used.
AvailabilityZone string `mapstructure:"availability_zone"` AvailabilityZone string `mapstructure:"availability_zone"`
......
package volumetypes package volumetypes
import ( import (
"github.com/racker/perigee"
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
) )
...@@ -45,11 +44,11 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes ...@@ -45,11 +44,11 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
return res return res
} }
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{ _, res.Err = client.Request("POST", createURL(client), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), MoreHeaders: client.AuthenticatedHeaders(),
OkCodes: []int{200, 201}, OkCodes: []int{200, 201},
ReqBody: &reqBody, JSONBody: &reqBody,
Results: &res.Body, JSONResponse: &res.Body,
}) })
return res return res
} }
...@@ -57,7 +56,7 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes ...@@ -57,7 +56,7 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
// Delete will delete the volume type with the provided ID. // Delete will delete the volume type with the provided ID.
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
var res DeleteResult var res DeleteResult
_, res.Err = perigee.Request("DELETE", deleteURL(client, id), perigee.Options{ _, res.Err = client.Request("DELETE", deleteURL(client, id), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), MoreHeaders: client.AuthenticatedHeaders(),
OkCodes: []int{202}, OkCodes: []int{202},
}) })
...@@ -68,10 +67,10 @@ func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { ...@@ -68,10 +67,10 @@ func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
// type from the result, call the Extract method on the GetResult. // type from the result, call the Extract method on the GetResult.
func Get(client *gophercloud.ServiceClient, id string) GetResult { func Get(client *gophercloud.ServiceClient, id string) GetResult {
var res GetResult var res GetResult
_, err := perigee.Request("GET", getURL(client, id), perigee.Options{ _, err := client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), MoreHeaders: client.AuthenticatedHeaders(),
OkCodes: []int{200}, OkCodes: []int{200},
Results: &res.Body, JSONResponse: &res.Body,
}) })
res.Err = err res.Err = err
return res return res
......
package base package base
import ( import "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud"
"github.com/racker/perigee"
)
// Get retrieves the home document, allowing the user to discover the // Get retrieves the home document, allowing the user to discover the
// entire API. // entire API.
func Get(c *gophercloud.ServiceClient) GetResult { func Get(c *gophercloud.ServiceClient) GetResult {
var res GetResult var res GetResult
_, res.Err = perigee.Request("GET", getURL(c), perigee.Options{ _, res.Err = c.Request("GET", getURL(c), gophercloud.RequestOpts{
MoreHeaders: c.AuthenticatedHeaders(), JSONResponse: &res.Body,
Results: &res.Body, OkCodes: []int{200},
OkCodes: []int{200},
}) })
return res return res
} }
...@@ -21,10 +16,9 @@ func Get(c *gophercloud.ServiceClient) GetResult { ...@@ -21,10 +16,9 @@ func Get(c *gophercloud.ServiceClient) GetResult {
// Ping retrieves a ping to the server. // Ping retrieves a ping to the server.
func Ping(c *gophercloud.ServiceClient) PingResult { func Ping(c *gophercloud.ServiceClient) PingResult {
var res PingResult var res PingResult
_, res.Err = perigee.Request("GET", pingURL(c), perigee.Options{ _, res.Err = c.Request("GET", pingURL(c), gophercloud.RequestOpts{
MoreHeaders: c.AuthenticatedHeaders(),
OkCodes: []int{204}, OkCodes: []int{204},
OmitAccept: true, MoreHeaders: map[string]string{"Accept": ""},
}) })
return res return res
} }
package flavors package flavors
import ( import (
"github.com/racker/perigee"
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
) )
...@@ -18,10 +17,9 @@ func List(c *gophercloud.ServiceClient) pagination.Pager { ...@@ -18,10 +17,9 @@ func List(c *gophercloud.ServiceClient) pagination.Pager {
// Get retrieves a specific flavor based on its unique ID. // Get retrieves a specific flavor based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) GetResult { func Get(c *gophercloud.ServiceClient, id string) GetResult {
var res GetResult var res GetResult
_, res.Err = perigee.Request("GET", getURL(c, id), perigee.Options{ _, res.Err = c.Request("GET", getURL(c, id), gophercloud.RequestOpts{
MoreHeaders: c.AuthenticatedHeaders(), JSONResponse: &res.Body,
Results: &res.Body, OkCodes: []int{200},
OkCodes: []int{200},
}) })
return res return res
} }
...@@ -3,7 +3,6 @@ package serviceassets ...@@ -3,7 +3,6 @@ package serviceassets
import ( import (
"strings" "strings"
"github.com/racker/perigee"
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
) )
...@@ -44,9 +43,8 @@ func Delete(c *gophercloud.ServiceClient, idOrURL string, opts DeleteOptsBuilder ...@@ -44,9 +43,8 @@ func Delete(c *gophercloud.ServiceClient, idOrURL string, opts DeleteOptsBuilder
} }
var res DeleteResult var res DeleteResult
_, res.Err = perigee.Request("DELETE", url, perigee.Options{ _, res.Err = c.Request("DELETE", url, gophercloud.RequestOpts{
MoreHeaders: c.AuthenticatedHeaders(), OkCodes: []int{202},
OkCodes: []int{202},
}) })
return res return res
} }
...@@ -4,7 +4,6 @@ import ( ...@@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/racker/perigee"
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
) )
...@@ -178,12 +177,11 @@ func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { ...@@ -178,12 +177,11 @@ func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
} }
// Send request to API // Send request to API
resp, err := perigee.Request("POST", createURL(c), perigee.Options{ resp, err := c.Request("POST", createURL(c), gophercloud.RequestOpts{
MoreHeaders: c.AuthenticatedHeaders(), JSONBody: &reqBody,
ReqBody: &reqBody, OkCodes: []int{202},
OkCodes: []int{202},
}) })
res.Header = resp.HttpResponse.Header res.Header = resp.Header
res.Err = err res.Err = err
return res return res
} }
...@@ -201,10 +199,9 @@ func Get(c *gophercloud.ServiceClient, idOrURL string) GetResult { ...@@ -201,10 +199,9 @@ func Get(c *gophercloud.ServiceClient, idOrURL string) GetResult {
} }
var res GetResult var res GetResult
_, res.Err = perigee.Request("GET", url, perigee.Options{ _, res.Err = c.Request("GET", url, gophercloud.RequestOpts{
MoreHeaders: c.AuthenticatedHeaders(), JSONResponse: &res.Body,
Results: &res.Body, OkCodes: []int{200},
OkCodes: []int{200},
}) })
return res return res
} }
...@@ -359,13 +356,12 @@ func Update(c *gophercloud.ServiceClient, idOrURL string, opts UpdateOpts) Updat ...@@ -359,13 +356,12 @@ func Update(c *gophercloud.ServiceClient, idOrURL string, opts UpdateOpts) Updat
reqBody[i] = patch.ToCDNServiceUpdateMap() reqBody[i] = patch.ToCDNServiceUpdateMap()
} }
resp, err := perigee.Request("PATCH", url, perigee.Options{ resp, err := c.Request("PATCH", url, gophercloud.RequestOpts{
MoreHeaders: c.AuthenticatedHeaders(), JSONBody: &reqBody,
ReqBody: &reqBody, OkCodes: []int{202},
OkCodes: []int{202},
}) })
var result UpdateResult var result UpdateResult
result.Header = resp.HttpResponse.Header result.Header = resp.Header
result.Err = err result.Err = err
return result return result
} }
...@@ -383,9 +379,8 @@ func Delete(c *gophercloud.ServiceClient, idOrURL string) DeleteResult { ...@@ -383,9 +379,8 @@ func Delete(c *gophercloud.ServiceClient, idOrURL string) DeleteResult {
} }
var res DeleteResult var res DeleteResult
_, res.Err = perigee.Request("DELETE", url, perigee.Options{ _, res.Err = c.Request("DELETE", url, gophercloud.RequestOpts{
MoreHeaders: c.AuthenticatedHeaders(), OkCodes: []int{202},
OkCodes: []int{202},
}) })
return res return res
} }
...@@ -68,7 +68,7 @@ func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOp ...@@ -68,7 +68,7 @@ func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOp
&utils.Version{ID: v30, Priority: 30, Suffix: "/v3/"}, &utils.Version{ID: v30, Priority: 30, Suffix: "/v3/"},
} }
chosen, endpoint, err := utils.ChooseVersion(client.IdentityBase, client.IdentityEndpoint, versions) chosen, endpoint, err := utils.ChooseVersion(client, versions)
if err != nil { if err != nil {
return err return err
} }
...@@ -107,6 +107,11 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc ...@@ -107,6 +107,11 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
return err return err
} }
if options.AllowReauth {
client.ReauthFunc = func() error {
return AuthenticateV2(client, options)
}
}
client.TokenID = token.ID client.TokenID = token.ID
client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) { client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
return V2EndpointURL(catalog, opts) return V2EndpointURL(catalog, opts)
...@@ -133,6 +138,11 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, options gopherc ...@@ -133,6 +138,11 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
} }
client.TokenID = token.ID client.TokenID = token.ID
if options.AllowReauth {
client.ReauthFunc = func() error {
return AuthenticateV3(client, options)
}
}
client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) { client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
return V3EndpointURL(v3Client, opts) return V3EndpointURL(v3Client, opts)
} }
...@@ -214,3 +224,13 @@ func NewCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) ( ...@@ -214,3 +224,13 @@ func NewCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (
} }
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
} }
// NewOrchestrationV1 creates a ServiceClient that may be used to access the v1 orchestration service.
func NewOrchestrationV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("orchestration")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
}
package extensions package extensions
import ( import (
"github.com/racker/perigee"
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
) )
...@@ -9,10 +8,9 @@ import ( ...@@ -9,10 +8,9 @@ import (
// Get retrieves information for a specific extension using its alias. // Get retrieves information for a specific extension using its alias.
func Get(c *gophercloud.ServiceClient, alias string) GetResult { func Get(c *gophercloud.ServiceClient, alias string) GetResult {
var res GetResult var res GetResult
_, res.Err = perigee.Request("GET", ExtensionURL(c, alias), perigee.Options{ _, res.Err = c.Request("GET", ExtensionURL(c, alias), gophercloud.RequestOpts{
MoreHeaders: c.AuthenticatedHeaders(), JSONResponse: &res.Body,
Results: &res.Body, OkCodes: []int{200},
OkCodes: []int{200},
}) })
return res return res
} }
......
...@@ -6,8 +6,6 @@ import ( ...@@ -6,8 +6,6 @@ import (
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack/compute/v2/servers" "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
"github.com/racker/perigee"
) )
// SourceType represents the type of medium being used to create the volume. // SourceType represents the type of medium being used to create the volume.
...@@ -101,11 +99,10 @@ func Create(client *gophercloud.ServiceClient, opts servers.CreateOptsBuilder) s ...@@ -101,11 +99,10 @@ func Create(client *gophercloud.ServiceClient, opts servers.CreateOptsBuilder) s
return res return res
} }
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{ _, res.Err = client.Request("POST", createURL(client), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), JSONBody: reqBody,
ReqBody: reqBody, JSONResponse: &res.Body,
Results: &res.Body, OkCodes: []int{200, 202},
OkCodes: []int{200, 202},
}) })
return res return res
} }
...@@ -3,8 +3,6 @@ package defsecrules ...@@ -3,8 +3,6 @@ package defsecrules
import ( import (
"errors" "errors"
"github.com/racker/perigee"
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
) )
...@@ -75,11 +73,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes ...@@ -75,11 +73,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
return result return result
} }
_, result.Err = perigee.Request("POST", rootURL(client), perigee.Options{ _, result.Err = client.Request("POST", rootURL(client), gophercloud.RequestOpts{
Results: &result.Body, JSONResponse: &result.Body,
ReqBody: &reqBody, JSONBody: &reqBody,
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200},
OkCodes: []int{200},
}) })
return result return result
...@@ -89,10 +86,9 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes ...@@ -89,10 +86,9 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
func Get(client *gophercloud.ServiceClient, id string) GetResult { func Get(client *gophercloud.ServiceClient, id string) GetResult {
var result GetResult var result GetResult
_, result.Err = perigee.Request("GET", resourceURL(client, id), perigee.Options{ _, result.Err = client.Request("GET", resourceURL(client, id), gophercloud.RequestOpts{
Results: &result.Body, JSONResponse: &result.Body,
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200},
OkCodes: []int{200},
}) })
return result return result
...@@ -102,9 +98,8 @@ func Get(client *gophercloud.ServiceClient, id string) GetResult { ...@@ -102,9 +98,8 @@ func Get(client *gophercloud.ServiceClient, id string) GetResult {
func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult { func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
var result gophercloud.ErrResult var result gophercloud.ErrResult
_, result.Err = perigee.Request("DELETE", resourceURL(client, id), perigee.Options{ _, result.Err = client.Request("DELETE", resourceURL(client, id), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{204},
OkCodes: []int{204},
}) })
return result return result
......
// Package floatingip provides the ability to manage floating ips through
// nova-network
package floatingip
// +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)
})
}
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.Request("POST", createURL(client), gophercloud.RequestOpts{
JSONBody: reqBody,
JSONResponse: &res.Body,
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.Request("GET", getURL(client, id), gophercloud.RequestOpts{
JSONResponse: &res.Body,
OkCodes: []int{200},
})
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.Request("DELETE", deleteURL(client, id), gophercloud.RequestOpts{
OkCodes: []int{202},
})
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.Request("POST", associateURL(client, serverId), gophercloud.RequestOpts{
JSONBody: reqBody,
OkCodes: []int{202},
})
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.Request("POST", disassociateURL(client, serverId), gophercloud.RequestOpts{
JSONBody: reqBody,
OkCodes: []int{202},
})
return res
}
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)
}
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
}
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)
}
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,7 +3,6 @@ package keypairs ...@@ -3,7 +3,6 @@ package keypairs
import ( import (
"errors" "errors"
"github.com/racker/perigee"
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack/compute/v2/servers" "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
...@@ -82,11 +81,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes ...@@ -82,11 +81,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
return res return res
} }
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{ _, res.Err = client.Request("POST", createURL(client), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), JSONBody: reqBody,
ReqBody: reqBody, JSONResponse: &res.Body,
Results: &res.Body, OkCodes: []int{200},
OkCodes: []int{200},
}) })
return res return res
} }
...@@ -94,10 +92,9 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes ...@@ -94,10 +92,9 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
// Get returns public data about a previously uploaded KeyPair. // Get returns public data about a previously uploaded KeyPair.
func Get(client *gophercloud.ServiceClient, name string) GetResult { func Get(client *gophercloud.ServiceClient, name string) GetResult {
var res GetResult var res GetResult
_, res.Err = perigee.Request("GET", getURL(client, name), perigee.Options{ _, res.Err = client.Request("GET", getURL(client, name), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), JSONResponse: &res.Body,
Results: &res.Body, OkCodes: []int{200},
OkCodes: []int{200},
}) })
return res return res
} }
...@@ -105,9 +102,8 @@ func Get(client *gophercloud.ServiceClient, name string) GetResult { ...@@ -105,9 +102,8 @@ func Get(client *gophercloud.ServiceClient, name string) GetResult {
// Delete requests the deletion of a previous stored KeyPair from the server. // Delete requests the deletion of a previous stored KeyPair from the server.
func Delete(client *gophercloud.ServiceClient, name string) DeleteResult { func Delete(client *gophercloud.ServiceClient, name string) DeleteResult {
var res DeleteResult var res DeleteResult
_, res.Err = perigee.Request("DELETE", deleteURL(client, name), perigee.Options{ _, res.Err = client.Request("DELETE", deleteURL(client, name), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{202},
OkCodes: []int{202},
}) })
return res return res
} }
...@@ -38,7 +38,7 @@ func mockListGroupsResponse(t *testing.T) { ...@@ -38,7 +38,7 @@ func mockListGroupsResponse(t *testing.T) {
} }
func mockListGroupsByServerResponse(t *testing.T, serverID string) { func mockListGroupsByServerResponse(t *testing.T, serverID string) {
url := fmt.Sprintf("%s/servers/%s%s", rootPath, serverID, rootPath) url := fmt.Sprintf("/servers/%s%s", serverID, rootPath)
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) { th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "GET") th.TestMethod(t, r, "GET")
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
......
...@@ -3,8 +3,6 @@ package secgroups ...@@ -3,8 +3,6 @@ package secgroups
import ( import (
"errors" "errors"
"github.com/racker/perigee"
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
) )
...@@ -80,11 +78,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes ...@@ -80,11 +78,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
return result return result
} }
_, result.Err = perigee.Request("POST", rootURL(client), perigee.Options{ _, result.Err = client.Request("POST", rootURL(client), gophercloud.RequestOpts{
Results: &result.Body, JSONResponse: &result.Body,
ReqBody: &reqBody, JSONBody: &reqBody,
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200},
OkCodes: []int{200},
}) })
return result return result
...@@ -126,11 +123,10 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder ...@@ -126,11 +123,10 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
return result return result
} }
_, result.Err = perigee.Request("PUT", resourceURL(client, id), perigee.Options{ _, result.Err = client.Request("PUT", resourceURL(client, id), gophercloud.RequestOpts{
Results: &result.Body, JSONResponse: &result.Body,
ReqBody: &reqBody, JSONBody: &reqBody,
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200},
OkCodes: []int{200},
}) })
return result return result
...@@ -140,10 +136,9 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder ...@@ -140,10 +136,9 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
func Get(client *gophercloud.ServiceClient, id string) GetResult { func Get(client *gophercloud.ServiceClient, id string) GetResult {
var result GetResult var result GetResult
_, result.Err = perigee.Request("GET", resourceURL(client, id), perigee.Options{ _, result.Err = client.Request("GET", resourceURL(client, id), gophercloud.RequestOpts{
Results: &result.Body, JSONResponse: &result.Body,
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200},
OkCodes: []int{200},
}) })
return result return result
...@@ -153,9 +148,8 @@ func Get(client *gophercloud.ServiceClient, id string) GetResult { ...@@ -153,9 +148,8 @@ func Get(client *gophercloud.ServiceClient, id string) GetResult {
func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult { func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
var result gophercloud.ErrResult var result gophercloud.ErrResult
_, result.Err = perigee.Request("DELETE", resourceURL(client, id), perigee.Options{ _, result.Err = client.Request("DELETE", resourceURL(client, id), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{202},
OkCodes: []int{202},
}) })
return result return result
...@@ -222,7 +216,7 @@ func (opts CreateRuleOpts) ToRuleCreateMap() (map[string]interface{}, error) { ...@@ -222,7 +216,7 @@ func (opts CreateRuleOpts) ToRuleCreateMap() (map[string]interface{}, error) {
rule["cidr"] = opts.CIDR rule["cidr"] = opts.CIDR
} }
if opts.FromGroupID != "" { if opts.FromGroupID != "" {
rule["from_group_id"] = opts.FromGroupID rule["group_id"] = opts.FromGroupID
} }
return map[string]interface{}{"security_group_rule": rule}, nil return map[string]interface{}{"security_group_rule": rule}, nil
...@@ -240,11 +234,10 @@ func CreateRule(client *gophercloud.ServiceClient, opts CreateRuleOptsBuilder) C ...@@ -240,11 +234,10 @@ func CreateRule(client *gophercloud.ServiceClient, opts CreateRuleOptsBuilder) C
return result return result
} }
_, result.Err = perigee.Request("POST", rootRuleURL(client), perigee.Options{ _, result.Err = client.Request("POST", rootRuleURL(client), gophercloud.RequestOpts{
Results: &result.Body, JSONResponse: &result.Body,
ReqBody: &reqBody, JSONBody: &reqBody,
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200},
OkCodes: []int{200},
}) })
return result return result
...@@ -254,9 +247,8 @@ func CreateRule(client *gophercloud.ServiceClient, opts CreateRuleOptsBuilder) C ...@@ -254,9 +247,8 @@ func CreateRule(client *gophercloud.ServiceClient, opts CreateRuleOptsBuilder) C
func DeleteRule(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult { func DeleteRule(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
var result gophercloud.ErrResult var result gophercloud.ErrResult
_, result.Err = perigee.Request("DELETE", resourceRuleURL(client, id), perigee.Options{ _, result.Err = client.Request("DELETE", resourceRuleURL(client, id), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{202},
OkCodes: []int{202},
}) })
return result return result
...@@ -273,11 +265,10 @@ func actionMap(prefix, groupName string) map[string]map[string]string { ...@@ -273,11 +265,10 @@ func actionMap(prefix, groupName string) map[string]map[string]string {
func AddServerToGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult { func AddServerToGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult {
var result gophercloud.ErrResult var result gophercloud.ErrResult
_, result.Err = perigee.Request("POST", serverActionURL(client, serverID), perigee.Options{ _, result.Err = client.Request("POST", serverActionURL(client, serverID), gophercloud.RequestOpts{
Results: &result.Body, JSONResponse: &result.Body,
ReqBody: actionMap("add", groupName), JSONBody: actionMap("add", groupName),
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{202},
OkCodes: []int{202},
}) })
return result return result
...@@ -287,11 +278,10 @@ func AddServerToGroup(client *gophercloud.ServiceClient, serverID, groupName str ...@@ -287,11 +278,10 @@ func AddServerToGroup(client *gophercloud.ServiceClient, serverID, groupName str
func RemoveServerFromGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult { func RemoveServerFromGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult {
var result gophercloud.ErrResult var result gophercloud.ErrResult
_, result.Err = perigee.Request("POST", serverActionURL(client, serverID), perigee.Options{ _, result.Err = client.Request("POST", serverActionURL(client, serverID), gophercloud.RequestOpts{
Results: &result.Body, JSONResponse: &result.Body,
ReqBody: actionMap("remove", groupName), JSONBody: actionMap("remove", groupName),
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{202},
OkCodes: []int{202},
}) })
return result return result
......
...@@ -16,7 +16,7 @@ func rootURL(c *gophercloud.ServiceClient) string { ...@@ -16,7 +16,7 @@ func rootURL(c *gophercloud.ServiceClient) string {
} }
func listByServerURL(c *gophercloud.ServiceClient, serverID string) string { func listByServerURL(c *gophercloud.ServiceClient, serverID string) string {
return c.ServiceURL(secgrouppath, "servers", serverID, secgrouppath) return c.ServiceURL("servers", serverID, secgrouppath)
} }
func rootRuleURL(c *gophercloud.ServiceClient) string { func rootRuleURL(c *gophercloud.ServiceClient) string {
......
package startstop package startstop
import ( import "github.com/rackspace/gophercloud"
"github.com/racker/perigee"
"github.com/rackspace/gophercloud"
)
func actionURL(client *gophercloud.ServiceClient, id string) string { func actionURL(client *gophercloud.ServiceClient, id string) string {
return client.ServiceURL("servers", id, "action") return client.ServiceURL("servers", id, "action")
...@@ -15,10 +12,9 @@ func Start(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult { ...@@ -15,10 +12,9 @@ func Start(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
reqBody := map[string]interface{}{"os-start": nil} reqBody := map[string]interface{}{"os-start": nil}
_, res.Err = perigee.Request("POST", actionURL(client, id), perigee.Options{ _, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), JSONBody: reqBody,
ReqBody: reqBody, OkCodes: []int{202},
OkCodes: []int{202},
}) })
return res return res
...@@ -30,10 +26,9 @@ func Stop(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult { ...@@ -30,10 +26,9 @@ func Stop(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
reqBody := map[string]interface{}{"os-stop": nil} reqBody := map[string]interface{}{"os-stop": nil}
_, res.Err = perigee.Request("POST", actionURL(client, id), perigee.Options{ _, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), JSONBody: reqBody,
ReqBody: reqBody, OkCodes: []int{202},
OkCodes: []int{202},
}) })
return res return res
......
// Package volumeattach provides the ability to attach and detach volumes
// to instances
package volumeattach
// +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)
})
}
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.Request("POST", createURL(client, serverId), gophercloud.RequestOpts{
JSONBody: reqBody,
JSONResponse: &res.Body,
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.Request("GET", getURL(client, serverId, aId), gophercloud.RequestOpts{
JSONResponse: &res.Body,
OkCodes: []int{200},
})
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.Request("DELETE", deleteURL(client, serverId, aId), gophercloud.RequestOpts{
OkCodes: []int{202},
})
return res
}
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)
}
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
}
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)
}
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))
}
package flavors package flavors
import ( import (
"github.com/racker/perigee"
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
) )
...@@ -64,9 +63,8 @@ func ListDetail(client *gophercloud.ServiceClient, opts ListOptsBuilder) paginat ...@@ -64,9 +63,8 @@ func ListDetail(client *gophercloud.ServiceClient, opts ListOptsBuilder) paginat
// Use ExtractFlavor to convert its result into a Flavor. // Use ExtractFlavor to convert its result into a Flavor.
func Get(client *gophercloud.ServiceClient, id string) GetResult { func Get(client *gophercloud.ServiceClient, id string) GetResult {
var gr GetResult var gr GetResult
gr.Err = perigee.Get(getURL(client, id), perigee.Options{ _, gr.Err = client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
Results: &gr.Body, JSONResponse: &gr.Body,
MoreHeaders: client.AuthenticatedHeaders(),
}) })
return gr return gr
} }
...@@ -3,8 +3,6 @@ package images ...@@ -3,8 +3,6 @@ package images
import ( import (
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
"github.com/racker/perigee"
) )
// ListOptsBuilder allows extensions to add additional parameters to the // ListOptsBuilder allows extensions to add additional parameters to the
...@@ -22,7 +20,7 @@ type ListOpts struct { ...@@ -22,7 +20,7 @@ type ListOpts struct {
// UUID of the Image at which to set a marker. // UUID of the Image at which to set a marker.
Marker string `q:"marker"` Marker string `q:"marker"`
// The name of the Image. // The name of the Image.
Name string `q:"name:"` Name string `q:"name"`
// The name of the Server (in URL format). // The name of the Server (in URL format).
Server string `q:"server"` Server string `q:"server"`
// The current status of the Image. // The current status of the Image.
...@@ -62,10 +60,9 @@ func ListDetail(client *gophercloud.ServiceClient, opts ListOptsBuilder) paginat ...@@ -62,10 +60,9 @@ func ListDetail(client *gophercloud.ServiceClient, opts ListOptsBuilder) paginat
// Use ExtractImage() to interpret the result as an openstack Image. // Use ExtractImage() to interpret the result as an openstack Image.
func Get(client *gophercloud.ServiceClient, id string) GetResult { func Get(client *gophercloud.ServiceClient, id string) GetResult {
var result GetResult var result GetResult
_, result.Err = perigee.Request("GET", getURL(client, id), perigee.Options{ _, result.Err = client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), JSONResponse: &result.Body,
Results: &result.Body, OkCodes: []int{200},
OkCodes: []int{200},
}) })
return result return result
} }
...@@ -285,6 +285,11 @@ var ( ...@@ -285,6 +285,11 @@ var (
Created: "2014-09-25T13:10:02Z", Created: "2014-09-25T13:10:02Z",
TenantID: "fcad67a6189847c4aecfa3c81a05783b", TenantID: "fcad67a6189847c4aecfa3c81a05783b",
Metadata: map[string]interface{}{}, Metadata: map[string]interface{}{},
SecurityGroups: []map[string]interface{}{
map[string]interface{}{
"name": "default",
},
},
} }
// ServerDerp is a Server struct that should correspond to the second server in ServerListBody. // ServerDerp is a Server struct that should correspond to the second server in ServerListBody.
...@@ -336,6 +341,11 @@ var ( ...@@ -336,6 +341,11 @@ var (
Created: "2014-09-25T13:04:41Z", Created: "2014-09-25T13:04:41Z",
TenantID: "fcad67a6189847c4aecfa3c81a05783b", TenantID: "fcad67a6189847c4aecfa3c81a05783b",
Metadata: map[string]interface{}{}, Metadata: map[string]interface{}{},
SecurityGroups: []map[string]interface{}{
map[string]interface{}{
"name": "default",
},
},
} }
) )
......
...@@ -5,7 +5,6 @@ import ( ...@@ -5,7 +5,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/racker/perigee"
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
) )
...@@ -217,11 +216,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes ...@@ -217,11 +216,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
return res return res
} }
_, res.Err = perigee.Request("POST", listURL(client), perigee.Options{ _, res.Err = client.Request("POST", listURL(client), gophercloud.RequestOpts{
Results: &res.Body, JSONResponse: &res.Body,
ReqBody: reqBody, JSONBody: reqBody,
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{202},
OkCodes: []int{202},
}) })
return res return res
} }
...@@ -229,9 +227,8 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes ...@@ -229,9 +227,8 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
// Delete requests that a server previously provisioned be removed from your account. // Delete requests that a server previously provisioned be removed from your account.
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
var res DeleteResult var res DeleteResult
_, res.Err = perigee.Request("DELETE", deleteURL(client, id), perigee.Options{ _, res.Err = client.Request("DELETE", deleteURL(client, id), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{204},
OkCodes: []int{204},
}) })
return res return res
} }
...@@ -239,10 +236,9 @@ func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { ...@@ -239,10 +236,9 @@ func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
// Get requests details on a single server, by ID. // Get requests details on a single server, by ID.
func Get(client *gophercloud.ServiceClient, id string) GetResult { func Get(client *gophercloud.ServiceClient, id string) GetResult {
var result GetResult var result GetResult
_, result.Err = perigee.Request("GET", getURL(client, id), perigee.Options{ _, result.Err = client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
Results: &result.Body, JSONResponse: &result.Body,
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200, 203},
OkCodes: []int{200, 203},
}) })
return result return result
} }
...@@ -284,10 +280,9 @@ func (opts UpdateOpts) ToServerUpdateMap() map[string]interface{} { ...@@ -284,10 +280,9 @@ func (opts UpdateOpts) ToServerUpdateMap() map[string]interface{} {
// Update requests that various attributes of the indicated server be changed. // Update requests that various attributes of the indicated server be changed.
func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult { func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
var result UpdateResult var result UpdateResult
_, result.Err = perigee.Request("PUT", updateURL(client, id), perigee.Options{ _, result.Err = client.Request("PUT", updateURL(client, id), gophercloud.RequestOpts{
Results: &result.Body, JSONResponse: &result.Body,
ReqBody: opts.ToServerUpdateMap(), JSONBody: opts.ToServerUpdateMap(),
MoreHeaders: client.AuthenticatedHeaders(),
}) })
return result return result
} }
...@@ -304,10 +299,9 @@ func ChangeAdminPassword(client *gophercloud.ServiceClient, id, newPassword stri ...@@ -304,10 +299,9 @@ func ChangeAdminPassword(client *gophercloud.ServiceClient, id, newPassword stri
var res ActionResult var res ActionResult
_, res.Err = perigee.Request("POST", actionURL(client, id), perigee.Options{ _, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
ReqBody: req, JSONBody: req,
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{202},
OkCodes: []int{202},
}) })
return res return res
...@@ -373,14 +367,13 @@ func Reboot(client *gophercloud.ServiceClient, id string, how RebootMethod) Acti ...@@ -373,14 +367,13 @@ func Reboot(client *gophercloud.ServiceClient, id string, how RebootMethod) Acti
return res return res
} }
_, res.Err = perigee.Request("POST", actionURL(client, id), perigee.Options{ _, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
ReqBody: struct { JSONBody: struct {
C map[string]string `json:"reboot"` C map[string]string `json:"reboot"`
}{ }{
map[string]string{"type": string(how)}, map[string]string{"type": string(how)},
}, },
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{202},
OkCodes: []int{202},
}) })
return res return res
...@@ -475,11 +468,10 @@ func Rebuild(client *gophercloud.ServiceClient, id string, opts RebuildOptsBuild ...@@ -475,11 +468,10 @@ func Rebuild(client *gophercloud.ServiceClient, id string, opts RebuildOptsBuild
return result return result
} }
_, result.Err = perigee.Request("POST", actionURL(client, id), perigee.Options{ _, result.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
ReqBody: &reqBody, JSONBody: &reqBody,
Results: &result.Body, JSONResponse: &result.Body,
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{202},
OkCodes: []int{202},
}) })
return result return result
...@@ -522,10 +514,9 @@ func Resize(client *gophercloud.ServiceClient, id string, opts ResizeOptsBuilder ...@@ -522,10 +514,9 @@ func Resize(client *gophercloud.ServiceClient, id string, opts ResizeOptsBuilder
return res return res
} }
_, res.Err = perigee.Request("POST", actionURL(client, id), perigee.Options{ _, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
ReqBody: reqBody, JSONBody: reqBody,
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{202},
OkCodes: []int{202},
}) })
return res return res
...@@ -536,10 +527,9 @@ func Resize(client *gophercloud.ServiceClient, id string, opts ResizeOptsBuilder ...@@ -536,10 +527,9 @@ func Resize(client *gophercloud.ServiceClient, id string, opts ResizeOptsBuilder
func ConfirmResize(client *gophercloud.ServiceClient, id string) ActionResult { func ConfirmResize(client *gophercloud.ServiceClient, id string) ActionResult {
var res ActionResult var res ActionResult
_, res.Err = perigee.Request("POST", actionURL(client, id), perigee.Options{ _, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
ReqBody: map[string]interface{}{"confirmResize": nil}, JSONBody: map[string]interface{}{"confirmResize": nil},
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{204},
OkCodes: []int{204},
}) })
return res return res
...@@ -550,10 +540,9 @@ func ConfirmResize(client *gophercloud.ServiceClient, id string) ActionResult { ...@@ -550,10 +540,9 @@ func ConfirmResize(client *gophercloud.ServiceClient, id string) ActionResult {
func RevertResize(client *gophercloud.ServiceClient, id string) ActionResult { func RevertResize(client *gophercloud.ServiceClient, id string) ActionResult {
var res ActionResult var res ActionResult
_, res.Err = perigee.Request("POST", actionURL(client, id), perigee.Options{ _, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
ReqBody: map[string]interface{}{"revertResize": nil}, JSONBody: map[string]interface{}{"revertResize": nil},
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{202},
OkCodes: []int{202},
}) })
return res return res
...@@ -597,11 +586,10 @@ func Rescue(client *gophercloud.ServiceClient, id string, opts RescueOptsBuilder ...@@ -597,11 +586,10 @@ func Rescue(client *gophercloud.ServiceClient, id string, opts RescueOptsBuilder
return result return result
} }
_, result.Err = perigee.Request("POST", actionURL(client, id), perigee.Options{ _, result.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
Results: &result.Body, JSONResponse: &result.Body,
ReqBody: &reqBody, JSONBody: &reqBody,
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200},
OkCodes: []int{200},
}) })
return result return result
...@@ -637,10 +625,9 @@ func ResetMetadata(client *gophercloud.ServiceClient, id string, opts ResetMetad ...@@ -637,10 +625,9 @@ func ResetMetadata(client *gophercloud.ServiceClient, id string, opts ResetMetad
res.Err = err res.Err = err
return res return res
} }
_, res.Err = perigee.Request("PUT", metadataURL(client, id), perigee.Options{ _, res.Err = client.Request("PUT", metadataURL(client, id), gophercloud.RequestOpts{
ReqBody: metadata, JSONBody: metadata,
Results: &res.Body, JSONResponse: &res.Body,
MoreHeaders: client.AuthenticatedHeaders(),
}) })
return res return res
} }
...@@ -648,9 +635,8 @@ func ResetMetadata(client *gophercloud.ServiceClient, id string, opts ResetMetad ...@@ -648,9 +635,8 @@ func ResetMetadata(client *gophercloud.ServiceClient, id string, opts ResetMetad
// Metadata requests all the metadata for the given server ID. // Metadata requests all the metadata for the given server ID.
func Metadata(client *gophercloud.ServiceClient, id string) GetMetadataResult { func Metadata(client *gophercloud.ServiceClient, id string) GetMetadataResult {
var res GetMetadataResult var res GetMetadataResult
_, res.Err = perigee.Request("GET", metadataURL(client, id), perigee.Options{ _, res.Err = client.Request("GET", metadataURL(client, id), gophercloud.RequestOpts{
Results: &res.Body, JSONResponse: &res.Body,
MoreHeaders: client.AuthenticatedHeaders(),
}) })
return res return res
} }
...@@ -671,10 +657,9 @@ func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMet ...@@ -671,10 +657,9 @@ func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMet
res.Err = err res.Err = err
return res return res
} }
_, res.Err = perigee.Request("POST", metadataURL(client, id), perigee.Options{ _, res.Err = client.Request("POST", metadataURL(client, id), gophercloud.RequestOpts{
ReqBody: metadata, JSONBody: metadata,
Results: &res.Body, JSONResponse: &res.Body,
MoreHeaders: client.AuthenticatedHeaders(),
}) })
return res return res
} }
...@@ -710,10 +695,9 @@ func CreateMetadatum(client *gophercloud.ServiceClient, id string, opts Metadatu ...@@ -710,10 +695,9 @@ func CreateMetadatum(client *gophercloud.ServiceClient, id string, opts Metadatu
return res return res
} }
_, res.Err = perigee.Request("PUT", metadatumURL(client, id, key), perigee.Options{ _, res.Err = client.Request("PUT", metadatumURL(client, id, key), gophercloud.RequestOpts{
ReqBody: metadatum, JSONBody: metadatum,
Results: &res.Body, JSONResponse: &res.Body,
MoreHeaders: client.AuthenticatedHeaders(),
}) })
return res return res
} }
...@@ -721,9 +705,8 @@ func CreateMetadatum(client *gophercloud.ServiceClient, id string, opts Metadatu ...@@ -721,9 +705,8 @@ func CreateMetadatum(client *gophercloud.ServiceClient, id string, opts Metadatu
// Metadatum requests the key-value pair with the given key for the given server ID. // Metadatum requests the key-value pair with the given key for the given server ID.
func Metadatum(client *gophercloud.ServiceClient, id, key string) GetMetadatumResult { func Metadatum(client *gophercloud.ServiceClient, id, key string) GetMetadatumResult {
var res GetMetadatumResult var res GetMetadatumResult
_, res.Err = perigee.Request("GET", metadatumURL(client, id, key), perigee.Options{ _, res.Err = client.Request("GET", metadatumURL(client, id, key), gophercloud.RequestOpts{
Results: &res.Body, JSONResponse: &res.Body,
MoreHeaders: client.AuthenticatedHeaders(),
}) })
return res return res
} }
...@@ -731,9 +714,8 @@ func Metadatum(client *gophercloud.ServiceClient, id, key string) GetMetadatumRe ...@@ -731,9 +714,8 @@ func Metadatum(client *gophercloud.ServiceClient, id, key string) GetMetadatumRe
// DeleteMetadatum will delete the key-value pair with the given key for the given server ID. // DeleteMetadatum will delete the key-value pair with the given key for the given server ID.
func DeleteMetadatum(client *gophercloud.ServiceClient, id, key string) DeleteMetadatumResult { func DeleteMetadatum(client *gophercloud.ServiceClient, id, key string) DeleteMetadatumResult {
var res DeleteMetadatumResult var res DeleteMetadatumResult
_, res.Err = perigee.Request("DELETE", metadatumURL(client, id, key), perigee.Options{ _, res.Err = client.Request("DELETE", metadatumURL(client, id, key), gophercloud.RequestOpts{
Results: &res.Body, JSONResponse: &res.Body,
MoreHeaders: client.AuthenticatedHeaders(),
}) })
return res return res
} }
...@@ -39,6 +39,19 @@ func TestListServers(t *testing.T) { ...@@ -39,6 +39,19 @@ func TestListServers(t *testing.T) {
} }
} }
func TestListAllServers(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
HandleServerListSuccessfully(t)
allPages, err := List(client.ServiceClient(), ListOpts{}).AllPages()
th.AssertNoErr(t, err)
actual, err := ExtractServers(allPages)
th.AssertNoErr(t, err)
th.CheckDeepEquals(t, ServerHerp, actual[0])
th.CheckDeepEquals(t, ServerDerp, actual[1])
}
func TestCreateServer(t *testing.T) { func TestCreateServer(t *testing.T) {
th.SetupHTTP() th.SetupHTTP()
defer th.TeardownHTTP() defer th.TeardownHTTP()
......
...@@ -139,6 +139,9 @@ type Server struct { ...@@ -139,6 +139,9 @@ type Server struct {
// AdminPass will generally be empty (""). However, it will contain the administrative password chosen when provisioning a new server without a set AdminPass setting in the first place. // AdminPass will generally be empty (""). However, it will contain the administrative password chosen when provisioning a new server without a set AdminPass setting in the first place.
// Note that this is the ONLY time this field will be valid. // Note that this is the ONLY time this field will be valid.
AdminPass string `json:"adminPass" mapstructure:"adminPass"` AdminPass string `json:"adminPass" mapstructure:"adminPass"`
// SecurityGroups includes the security groups that this instance has applied to it
SecurityGroups []map[string]interface{} `json:"security_groups" mapstructure:"security_groups"`
} }
// ServerPage abstracts the raw results of making a List() request against the API. // ServerPage abstracts the raw results of making a List() request against the API.
......
package roles package roles
import ( import (
"github.com/racker/perigee"
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
) )
...@@ -21,9 +20,8 @@ func List(client *gophercloud.ServiceClient) pagination.Pager { ...@@ -21,9 +20,8 @@ func List(client *gophercloud.ServiceClient) pagination.Pager {
func AddUserRole(client *gophercloud.ServiceClient, tenantID, userID, roleID string) UserRoleResult { func AddUserRole(client *gophercloud.ServiceClient, tenantID, userID, roleID string) UserRoleResult {
var result UserRoleResult var result UserRoleResult
_, result.Err = perigee.Request("PUT", userRoleURL(client, tenantID, userID, roleID), perigee.Options{ _, result.Err = client.Request("PUT", userRoleURL(client, tenantID, userID, roleID), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200, 201},
OkCodes: []int{200, 201},
}) })
return result return result
...@@ -35,9 +33,8 @@ func AddUserRole(client *gophercloud.ServiceClient, tenantID, userID, roleID str ...@@ -35,9 +33,8 @@ func AddUserRole(client *gophercloud.ServiceClient, tenantID, userID, roleID str
func DeleteUserRole(client *gophercloud.ServiceClient, tenantID, userID, roleID string) UserRoleResult { func DeleteUserRole(client *gophercloud.ServiceClient, tenantID, userID, roleID string) UserRoleResult {
var result UserRoleResult var result UserRoleResult
_, result.Err = perigee.Request("DELETE", userRoleURL(client, tenantID, userID, roleID), perigee.Options{ _, result.Err = client.Request("DELETE", userRoleURL(client, tenantID, userID, roleID), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{204},
OkCodes: []int{204},
}) })
return result return result
......
package tokens package tokens
import ( import "github.com/rackspace/gophercloud"
"github.com/racker/perigee"
"github.com/rackspace/gophercloud"
)
// AuthOptionsBuilder describes any argument that may be passed to the Create call. // AuthOptionsBuilder describes any argument that may be passed to the Create call.
type AuthOptionsBuilder interface { type AuthOptionsBuilder interface {
...@@ -78,10 +75,10 @@ func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) CreateRe ...@@ -78,10 +75,10 @@ func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) CreateRe
} }
var result CreateResult var result CreateResult
_, result.Err = perigee.Request("POST", CreateURL(client), perigee.Options{ _, result.Err = client.Request("POST", CreateURL(client), gophercloud.RequestOpts{
ReqBody: &request, JSONBody: &request,
Results: &result.Body, JSONResponse: &result.Body,
OkCodes: []int{200, 203}, OkCodes: []int{200, 203},
}) })
return result return result
} }
...@@ -3,7 +3,6 @@ package users ...@@ -3,7 +3,6 @@ package users
import ( import (
"errors" "errors"
"github.com/racker/perigee"
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
) )
...@@ -91,11 +90,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes ...@@ -91,11 +90,10 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
return res return res
} }
_, res.Err = perigee.Request("POST", rootURL(client), perigee.Options{ _, res.Err = client.Request("POST", rootURL(client), gophercloud.RequestOpts{
Results: &res.Body, JSONResponse: &res.Body,
ReqBody: reqBody, JSONBody: reqBody,
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200, 201},
OkCodes: []int{200, 201},
}) })
return res return res
...@@ -105,10 +103,9 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes ...@@ -105,10 +103,9 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateRes
func Get(client *gophercloud.ServiceClient, id string) GetResult { func Get(client *gophercloud.ServiceClient, id string) GetResult {
var result GetResult var result GetResult
_, result.Err = perigee.Request("GET", ResourceURL(client, id), perigee.Options{ _, result.Err = client.Request("GET", ResourceURL(client, id), gophercloud.RequestOpts{
Results: &result.Body, JSONResponse: &result.Body,
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200},
OkCodes: []int{200},
}) })
return result return result
...@@ -149,11 +146,10 @@ func (opts UpdateOpts) ToUserUpdateMap() map[string]interface{} { ...@@ -149,11 +146,10 @@ func (opts UpdateOpts) ToUserUpdateMap() map[string]interface{} {
func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult { func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
var result UpdateResult var result UpdateResult
_, result.Err = perigee.Request("PUT", ResourceURL(client, id), perigee.Options{ _, result.Err = client.Request("PUT", ResourceURL(client, id), gophercloud.RequestOpts{
Results: &result.Body, JSONResponse: &result.Body,
ReqBody: opts.ToUserUpdateMap(), JSONBody: opts.ToUserUpdateMap(),
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{200},
OkCodes: []int{200},
}) })
return result return result
...@@ -163,9 +159,8 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder ...@@ -163,9 +159,8 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult { func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
var result DeleteResult var result DeleteResult
_, result.Err = perigee.Request("DELETE", ResourceURL(client, id), perigee.Options{ _, result.Err = client.Request("DELETE", ResourceURL(client, id), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{204},
OkCodes: []int{204},
}) })
return result return result
......
package endpoints package endpoints
import ( import (
"github.com/racker/perigee"
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
) )
...@@ -57,11 +56,10 @@ func Create(client *gophercloud.ServiceClient, opts EndpointOpts) CreateResult { ...@@ -57,11 +56,10 @@ func Create(client *gophercloud.ServiceClient, opts EndpointOpts) CreateResult {
reqBody.Endpoint.Region = gophercloud.MaybeString(opts.Region) reqBody.Endpoint.Region = gophercloud.MaybeString(opts.Region)
var result CreateResult var result CreateResult
_, result.Err = perigee.Request("POST", listURL(client), perigee.Options{ _, result.Err = client.Request("POST", listURL(client), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), JSONBody: &reqBody,
ReqBody: &reqBody, JSONResponse: &result.Body,
Results: &result.Body, OkCodes: []int{201},
OkCodes: []int{201},
}) })
return result return result
} }
...@@ -113,11 +111,10 @@ func Update(client *gophercloud.ServiceClient, endpointID string, opts EndpointO ...@@ -113,11 +111,10 @@ func Update(client *gophercloud.ServiceClient, endpointID string, opts EndpointO
reqBody.Endpoint.ServiceID = gophercloud.MaybeString(opts.ServiceID) reqBody.Endpoint.ServiceID = gophercloud.MaybeString(opts.ServiceID)
var result UpdateResult var result UpdateResult
_, result.Err = perigee.Request("PATCH", endpointURL(client, endpointID), perigee.Options{ _, result.Err = client.Request("PATCH", endpointURL(client, endpointID), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), JSONBody: &reqBody,
ReqBody: &reqBody, JSONResponse: &result.Body,
Results: &result.Body, OkCodes: []int{200},
OkCodes: []int{200},
}) })
return result return result
} }
...@@ -125,9 +122,8 @@ func Update(client *gophercloud.ServiceClient, endpointID string, opts EndpointO ...@@ -125,9 +122,8 @@ func Update(client *gophercloud.ServiceClient, endpointID string, opts EndpointO
// Delete removes an endpoint from the service catalog. // Delete removes an endpoint from the service catalog.
func Delete(client *gophercloud.ServiceClient, endpointID string) DeleteResult { func Delete(client *gophercloud.ServiceClient, endpointID string) DeleteResult {
var res DeleteResult var res DeleteResult
_, res.Err = perigee.Request("DELETE", endpointURL(client, endpointID), perigee.Options{ _, res.Err = client.Request("DELETE", endpointURL(client, endpointID), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{204},
OkCodes: []int{204},
}) })
return res return res
} }
package services package services
import ( import (
"github.com/racker/perigee"
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination" "github.com/rackspace/gophercloud/pagination"
) )
...@@ -19,11 +18,10 @@ func Create(client *gophercloud.ServiceClient, serviceType string) CreateResult ...@@ -19,11 +18,10 @@ func Create(client *gophercloud.ServiceClient, serviceType string) CreateResult
req := request{Type: serviceType} req := request{Type: serviceType}
var result CreateResult var result CreateResult
_, result.Err = perigee.Request("POST", listURL(client), perigee.Options{ _, result.Err = client.Request("POST", listURL(client), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), JSONBody: &req,
ReqBody: &req, JSONResponse: &result.Body,
Results: &result.Body, OkCodes: []int{201},
OkCodes: []int{201},
}) })
return result return result
} }
...@@ -53,10 +51,9 @@ func List(client *gophercloud.ServiceClient, opts ListOpts) pagination.Pager { ...@@ -53,10 +51,9 @@ func List(client *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
// Get returns additional information about a service, given its ID. // Get returns additional information about a service, given its ID.
func Get(client *gophercloud.ServiceClient, serviceID string) GetResult { func Get(client *gophercloud.ServiceClient, serviceID string) GetResult {
var result GetResult var result GetResult
_, result.Err = perigee.Request("GET", serviceURL(client, serviceID), perigee.Options{ _, result.Err = client.Request("GET", serviceURL(client, serviceID), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), JSONResponse: &result.Body,
Results: &result.Body, OkCodes: []int{200},
OkCodes: []int{200},
}) })
return result return result
} }
...@@ -70,11 +67,10 @@ func Update(client *gophercloud.ServiceClient, serviceID string, serviceType str ...@@ -70,11 +67,10 @@ func Update(client *gophercloud.ServiceClient, serviceID string, serviceType str
req := request{Type: serviceType} req := request{Type: serviceType}
var result UpdateResult var result UpdateResult
_, result.Err = perigee.Request("PATCH", serviceURL(client, serviceID), perigee.Options{ _, result.Err = client.Request("PATCH", serviceURL(client, serviceID), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), JSONBody: &req,
ReqBody: &req, JSONResponse: &result.Body,
Results: &result.Body, OkCodes: []int{200},
OkCodes: []int{200},
}) })
return result return result
} }
...@@ -83,9 +79,8 @@ func Update(client *gophercloud.ServiceClient, serviceID string, serviceType str ...@@ -83,9 +79,8 @@ func Update(client *gophercloud.ServiceClient, serviceID string, serviceType str
// It either deletes all associated endpoints, or fails until all endpoints are deleted. // It either deletes all associated endpoints, or fails until all endpoints are deleted.
func Delete(client *gophercloud.ServiceClient, serviceID string) DeleteResult { func Delete(client *gophercloud.ServiceClient, serviceID string) DeleteResult {
var res DeleteResult var res DeleteResult
_, res.Err = perigee.Request("DELETE", serviceURL(client, serviceID), perigee.Options{ _, res.Err = client.Request("DELETE", serviceURL(client, serviceID), gophercloud.RequestOpts{
MoreHeaders: client.AuthenticatedHeaders(), OkCodes: []int{204},
OkCodes: []int{204},
}) })
return res return res
} }
package tokens package tokens
import ( import (
"github.com/racker/perigee" "net/http"
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
) )
...@@ -233,38 +234,38 @@ func Create(c *gophercloud.ServiceClient, options gophercloud.AuthOptions, scope ...@@ -233,38 +234,38 @@ func Create(c *gophercloud.ServiceClient, options gophercloud.AuthOptions, scope
} }
var result CreateResult var result CreateResult
var response *perigee.Response var response *http.Response
response, result.Err = perigee.Request("POST", tokenURL(c), perigee.Options{ response, result.Err = c.Request("POST", tokenURL(c), gophercloud.RequestOpts{
ReqBody: &req, JSONBody: &req,
Results: &result.Body, JSONResponse: &result.Body,
OkCodes: []int{201}, OkCodes: []int{201},
}) })
if result.Err != nil { if result.Err != nil {
return result return result
} }
result.Header = response.HttpResponse.Header result.Header = response.Header
return result return result
} }
// Get validates and retrieves information about another token. // Get validates and retrieves information about another token.
func Get(c *gophercloud.ServiceClient, token string) GetResult { func Get(c *gophercloud.ServiceClient, token string) GetResult {
var result GetResult var result GetResult
var response *perigee.Response var response *http.Response
response, result.Err = perigee.Request("GET", tokenURL(c), perigee.Options{ response, result.Err = c.Request("GET", tokenURL(c), gophercloud.RequestOpts{
MoreHeaders: subjectTokenHeaders(c, token), MoreHeaders: subjectTokenHeaders(c, token),
Results: &result.Body, JSONResponse: &result.Body,
OkCodes: []int{200, 203}, OkCodes: []int{200, 203},
}) })
if result.Err != nil { if result.Err != nil {
return result return result
} }
result.Header = response.HttpResponse.Header result.Header = response.Header
return result return result
} }
// Validate determines if a specified token is valid or not. // Validate determines if a specified token is valid or not.
func Validate(c *gophercloud.ServiceClient, token string) (bool, error) { func Validate(c *gophercloud.ServiceClient, token string) (bool, error) {
response, err := perigee.Request("HEAD", tokenURL(c), perigee.Options{ response, err := c.Request("HEAD", tokenURL(c), gophercloud.RequestOpts{
MoreHeaders: subjectTokenHeaders(c, token), MoreHeaders: subjectTokenHeaders(c, token),
OkCodes: []int{204, 404}, OkCodes: []int{204, 404},
}) })
...@@ -278,7 +279,7 @@ func Validate(c *gophercloud.ServiceClient, token string) (bool, error) { ...@@ -278,7 +279,7 @@ func Validate(c *gophercloud.ServiceClient, token string) (bool, error) {
// Revoke immediately makes specified token invalid. // Revoke immediately makes specified token invalid.
func Revoke(c *gophercloud.ServiceClient, token string) RevokeResult { func Revoke(c *gophercloud.ServiceClient, token string) RevokeResult {
var res RevokeResult var res RevokeResult
_, res.Err = perigee.Request("DELETE", tokenURL(c), perigee.Options{ _, res.Err = c.Request("DELETE", tokenURL(c), gophercloud.RequestOpts{
MoreHeaders: subjectTokenHeaders(c, token), MoreHeaders: subjectTokenHeaders(c, token),
OkCodes: []int{204}, OkCodes: []int{204},
}) })
......
// Package fwaas provides information and interaction with the Firewall
// as a Service extension for the OpenStack Networking service.
package fwaas
package firewalls
import "fmt"
func err(str string) error {
return fmt.Errorf("%s", str)
}
var (
errPolicyRequired = err("A policy ID is required")
)
package firewalls
import (
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// AdminState gives users a solid type to work with for create and update
// operations. It is recommended that users use the `Up` and `Down` enums.
type AdminState *bool
// Shared gives users a solid type to work with for create and update
// operations. It is recommended that users use the `Yes` and `No` enums.
type Shared *bool
// Convenience vars for AdminStateUp and Shared values.
var (
iTrue = true
iFalse = false
Up AdminState = &iTrue
Down AdminState = &iFalse
Yes Shared = &iTrue
No Shared = &iFalse
)
// ListOptsBuilder allows extensions to add additional parameters to the
// List request.
type ListOptsBuilder interface {
ToFirewallListQuery() (string, error)
}
// ListOpts allows the filtering and sorting of paginated collections through
// the API. Filtering is achieved by passing in struct field values that map to
// the firewall attributes you want to see returned. SortKey allows you to sort
// by a particular firewall attribute. SortDir sets the direction, and is either
// `asc' or `desc'. Marker and Limit are used for pagination.
type ListOpts struct {
TenantID string `q:"tenant_id"`
Name string `q:"name"`
Description string `q:"description"`
AdminStateUp bool `q:"admin_state_up"`
Shared bool `q:"shared"`
PolicyID string `q:"firewall_policy_id"`
ID string `q:"id"`
Limit int `q:"limit"`
Marker string `q:"marker"`
SortKey string `q:"sort_key"`
SortDir string `q:"sort_dir"`
}
// ToFirewallListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToFirewallListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return "", err
}
return q.String(), nil
}
// List returns a Pager which allows you to iterate over a collection of
// firewalls. It accepts a ListOpts struct, which allows you to filter
// and sort the returned collection for greater efficiency.
//
// Default policy settings return only those firewalls that are owned by the
// tenant who submits the request, unless an admin user submits the request.
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
url := rootURL(c)
if opts != nil {
query, err := opts.ToFirewallListQuery()
if err != nil {
return pagination.Pager{Err: err}
}
url += query
}
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
return FirewallPage{pagination.LinkedPageBase{PageResult: r}}
})
}
// CreateOptsBuilder is the interface options structs have to satisfy in order
// to be used in the main Create operation in this package. Since many
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type CreateOptsBuilder interface {
ToFirewallCreateMap() (map[string]interface{}, error)
}
// CreateOpts contains all the values needed to create a new firewall.
type CreateOpts struct {
// Only required if the caller has an admin role and wants to create a firewall
// for another tenant.
TenantID string
Name string
Description string
AdminStateUp *bool
Shared *bool
PolicyID string
}
// ToFirewallCreateMap casts a CreateOpts struct to a map.
func (opts CreateOpts) ToFirewallCreateMap() (map[string]interface{}, error) {
if opts.PolicyID == "" {
return nil, errPolicyRequired
}
f := make(map[string]interface{})
if opts.TenantID != "" {
f["tenant_id"] = opts.TenantID
}
if opts.Name != "" {
f["name"] = opts.Name
}
if opts.Description != "" {
f["description"] = opts.Description
}
if opts.Shared != nil {
f["shared"] = *opts.Shared
}
if opts.AdminStateUp != nil {
f["admin_state_up"] = *opts.AdminStateUp
}
if opts.PolicyID != "" {
f["firewall_policy_id"] = opts.PolicyID
}
return map[string]interface{}{"firewall": f}, nil
}
// Create accepts a CreateOpts struct and uses the values to create a new firewall
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
var res CreateResult
reqBody, err := opts.ToFirewallCreateMap()
if err != nil {
res.Err = err
return res
}
_, res.Err = c.Request("POST", rootURL(c), gophercloud.RequestOpts{
JSONBody: &reqBody,
JSONResponse: &res.Body,
OkCodes: []int{201},
})
return res
}
// Get retrieves a particular firewall based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) GetResult {
var res GetResult
_, res.Err = c.Request("GET", resourceURL(c, id), gophercloud.RequestOpts{
JSONResponse: &res.Body,
OkCodes: []int{200},
})
return res
}
// UpdateOptsBuilder is the interface options structs have to satisfy in order
// to be used in the main Update operation in this package. Since many
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type UpdateOptsBuilder interface {
ToFirewallUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts contains the values used when updating a firewall.
type UpdateOpts struct {
// Name of the firewall.
Name string
Description string
AdminStateUp *bool
Shared *bool
PolicyID string
}
// ToFirewallUpdateMap casts a CreateOpts struct to a map.
func (opts UpdateOpts) ToFirewallUpdateMap() (map[string]interface{}, error) {
f := make(map[string]interface{})
if opts.Name != "" {
f["name"] = opts.Name
}
if opts.Description != "" {
f["description"] = opts.Description
}
if opts.Shared != nil {
f["shared"] = *opts.Shared
}
if opts.AdminStateUp != nil {
f["admin_state_up"] = *opts.AdminStateUp
}
if opts.PolicyID != "" {
f["firewall_policy_id"] = opts.PolicyID
}
return map[string]interface{}{"firewall": f}, nil
}
// Update allows firewalls to be updated.
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
var res UpdateResult
reqBody, err := opts.ToFirewallUpdateMap()
if err != nil {
res.Err = err
return res
}
// Send request to API
_, res.Err = c.Request("PUT", resourceURL(c, id), gophercloud.RequestOpts{
JSONBody: &reqBody,
JSONResponse: &res.Body,
OkCodes: []int{200},
})
return res
}
// Delete will permanently delete a particular firewall based on its unique ID.
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
var res DeleteResult
_, res.Err = c.Request("DELETE", resourceURL(c, id), gophercloud.RequestOpts{
OkCodes: []int{204},
})
return res
}
package firewalls
import (
"fmt"
"net/http"
"testing"
fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
"github.com/rackspace/gophercloud/pagination"
th "github.com/rackspace/gophercloud/testhelper"
)
func TestURLs(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
th.AssertEquals(t, th.Endpoint()+"v2.0/fw/firewalls", rootURL(fake.ServiceClient()))
}
func TestList(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
th.Mux.HandleFunc("/v2.0/fw/firewalls", 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, `
{
"firewalls":[
{
"status": "ACTIVE",
"name": "fw1",
"admin_state_up": false,
"tenant_id": "b4eedccc6fb74fa8a7ad6b08382b852b",
"firewall_policy_id": "34be8c83-4d42-4dca-a74e-b77fffb8e28a",
"id": "fb5b5315-64f6-4ea3-8e58-981cc37c6f61",
"description": "OpenStack firewall 1"
},
{
"status": "PENDING_UPDATE",
"name": "fw2",
"admin_state_up": true,
"tenant_id": "b4eedccc6fb74fa8a7ad6b08382b852b",
"firewall_policy_id": "34be8c83-4d42-4dca-a74e-b77fffb8e299",
"id": "fb5b5315-64f6-4ea3-8e58-981cc37c6f99",
"description": "OpenStack firewall 2"
}
]
}
`)
})
count := 0
List(fake.ServiceClient(), ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
count++
actual, err := ExtractFirewalls(page)
if err != nil {
t.Errorf("Failed to extract members: %v", err)
return false, err
}
expected := []Firewall{
Firewall{
Status: "ACTIVE",
Name: "fw1",
AdminStateUp: false,
TenantID: "b4eedccc6fb74fa8a7ad6b08382b852b",
PolicyID: "34be8c83-4d42-4dca-a74e-b77fffb8e28a",
ID: "fb5b5315-64f6-4ea3-8e58-981cc37c6f61",
Description: "OpenStack firewall 1",
},
Firewall{
Status: "PENDING_UPDATE",
Name: "fw2",
AdminStateUp: true,
TenantID: "b4eedccc6fb74fa8a7ad6b08382b852b",
PolicyID: "34be8c83-4d42-4dca-a74e-b77fffb8e299",
ID: "fb5b5315-64f6-4ea3-8e58-981cc37c6f99",
Description: "OpenStack firewall 2",
},
}
th.CheckDeepEquals(t, expected, actual)
return true, nil
})
if count != 1 {
t.Errorf("Expected 1 page, got %d", count)
}
}
func TestCreate(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
th.Mux.HandleFunc("/v2.0/fw/firewalls", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "POST")
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
th.TestHeader(t, r, "Content-Type", "application/json")
th.TestHeader(t, r, "Accept", "application/json")
th.TestJSONRequest(t, r, `
{
"firewall":{
"name": "fw",
"description": "OpenStack firewall",
"admin_state_up": true,
"firewall_policy_id": "19ab8c87-4a32-4e6a-a74e-b77fffb89a0c",
"tenant_id": "b4eedccc6fb74fa8a7ad6b08382b852b"
}
}
`)
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
fmt.Fprintf(w, `
{
"firewall":{
"status": "PENDING_CREATE",
"name": "fw",
"description": "OpenStack firewall",
"admin_state_up": true,
"tenant_id": "b4eedccc6fb74fa8a7ad6b08382b852b",
"firewall_policy_id": "19ab8c87-4a32-4e6a-a74e-b77fffb89a0c"
}
}
`)
})
options := CreateOpts{
TenantID: "b4eedccc6fb74fa8a7ad6b08382b852b",
Name: "fw",
Description: "OpenStack firewall",
AdminStateUp: Up,
PolicyID: "19ab8c87-4a32-4e6a-a74e-b77fffb89a0c",
}
_, err := Create(fake.ServiceClient(), options).Extract()
th.AssertNoErr(t, err)
}
func TestGet(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
th.Mux.HandleFunc("/v2.0/fw/firewalls/fb5b5315-64f6-4ea3-8e58-981cc37c6f61", 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, `
{
"firewall": {
"status": "ACTIVE",
"name": "fw",
"admin_state_up": true,
"tenant_id": "b4eedccc6fb74fa8a7ad6b08382b852b",
"firewall_policy_id": "34be8c83-4d42-4dca-a74e-b77fffb8e28a",
"id": "fb5b5315-64f6-4ea3-8e58-981cc37c6f61",
"description": "OpenStack firewall"
}
}
`)
})
fw, err := Get(fake.ServiceClient(), "fb5b5315-64f6-4ea3-8e58-981cc37c6f61").Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, "ACTIVE", fw.Status)
th.AssertEquals(t, "fw", fw.Name)
th.AssertEquals(t, "OpenStack firewall", fw.Description)
th.AssertEquals(t, true, fw.AdminStateUp)
th.AssertEquals(t, "34be8c83-4d42-4dca-a74e-b77fffb8e28a", fw.PolicyID)
th.AssertEquals(t, "fb5b5315-64f6-4ea3-8e58-981cc37c6f61", fw.ID)
th.AssertEquals(t, "b4eedccc6fb74fa8a7ad6b08382b852b", fw.TenantID)
}
func TestUpdate(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
th.Mux.HandleFunc("/v2.0/fw/firewalls/ea5b5315-64f6-4ea3-8e58-981cc37c6576", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "PUT")
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
th.TestHeader(t, r, "Content-Type", "application/json")
th.TestHeader(t, r, "Accept", "application/json")
th.TestJSONRequest(t, r, `
{
"firewall":{
"name": "fw",
"description": "updated fw",
"admin_state_up":false,
"firewall_policy_id": "19ab8c87-4a32-4e6a-a74e-b77fffb89a0c"
}
}
`)
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, `
{
"firewall": {
"status": "ACTIVE",
"name": "fw",
"admin_state_up": false,
"tenant_id": "b4eedccc6fb74fa8a7ad6b08382b852b",
"firewall_policy_id": "19ab8c87-4a32-4e6a-a74e-b77fffb89a0c"
"id": "ea5b5315-64f6-4ea3-8e58-981cc37c6576",
"description": "OpenStack firewall",
}
}
`)
})
options := UpdateOpts{
Name: "fw",
Description: "updated fw",
AdminStateUp: Down,
PolicyID: "19ab8c87-4a32-4e6a-a74e-b77fffb89a0c",
}
_, err := Update(fake.ServiceClient(), "ea5b5315-64f6-4ea3-8e58-981cc37c6576", options).Extract()
th.AssertNoErr(t, err)
}
func TestDelete(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
th.Mux.HandleFunc("/v2.0/fw/firewalls/4ec89087-d057-4e2c-911f-60a3b47ee304", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "DELETE")
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
w.WriteHeader(http.StatusNoContent)
})
res := Delete(fake.ServiceClient(), "4ec89087-d057-4e2c-911f-60a3b47ee304")
th.AssertNoErr(t, res.Err)
}
package firewalls
import (
"github.com/mitchellh/mapstructure"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
type Firewall struct {
ID string `json:"id" mapstructure:"id"`
Name string `json:"name" mapstructure:"name"`
Description string `json:"description" mapstructure:"description"`
AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
Status string `json:"status" mapstructure:"status"`
PolicyID string `json:"firewall_policy_id" mapstructure:"firewall_policy_id"`
TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
}
type commonResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts a firewall.
func (r commonResult) Extract() (*Firewall, error) {
if r.Err != nil {
return nil, r.Err
}
var res struct {
Firewall *Firewall `json:"firewall"`
}
err := mapstructure.Decode(r.Body, &res)
return res.Firewall, err
}
// FirewallPage is the page returned by a pager when traversing over a
// collection of firewalls.
type FirewallPage struct {
pagination.LinkedPageBase
}
// NextPageURL is invoked when a paginated collection of firewalls has reached
// the end of a page and the pager seeks to traverse over a new one. In order
// to do this, it needs to construct the next page's URL.
func (p FirewallPage) NextPageURL() (string, error) {
type resp struct {
Links []gophercloud.Link `mapstructure:"firewalls_links"`
}
var r resp
err := mapstructure.Decode(p.Body, &r)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(r.Links)
}
// IsEmpty checks whether a FirewallPage struct is empty.
func (p FirewallPage) IsEmpty() (bool, error) {
is, err := ExtractFirewalls(p)
if err != nil {
return true, nil
}
return len(is) == 0, nil
}
// ExtractFirewalls accepts a Page struct, specifically a RouterPage struct,
// and extracts the elements into a slice of Router structs. In other words,
// a generic collection is mapped into a relevant slice.
func ExtractFirewalls(page pagination.Page) ([]Firewall, error) {
var resp struct {
Firewalls []Firewall `mapstructure:"firewalls" json:"firewalls"`
}
err := mapstructure.Decode(page.(FirewallPage).Body, &resp)
return resp.Firewalls, err
}
// GetResult represents the result of a get operation.
type GetResult struct {
commonResult
}
// UpdateResult represents the result of an update operation.
type UpdateResult struct {
commonResult
}
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
gophercloud.ErrResult
}
// CreateResult represents the result of a create operation.
type CreateResult struct {
commonResult
}
package firewalls
import "github.com/rackspace/gophercloud"
const (
rootPath = "fw"
resourcePath = "firewalls"
)
func rootURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL(rootPath, resourcePath)
}
func resourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(rootPath, resourcePath, id)
}
package policies
import (
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// Binary gives users a solid type to work with for create and update
// operations. It is recommended that users use the `Yes` and `No` enums
type Binary *bool
// Convenience vars for Audited and Shared values.
var (
iTrue = true
iFalse = false
Yes Binary = &iTrue
No Binary = &iFalse
)
// ListOptsBuilder allows extensions to add additional parameters to the
// List request.
type ListOptsBuilder interface {
ToPolicyListQuery() (string, error)
}
// ListOpts allows the filtering and sorting of paginated collections through
// the API. Filtering is achieved by passing in struct field values that map to
// the firewall policy attributes you want to see returned. SortKey allows you
// to sort by a particular firewall policy attribute. SortDir sets the direction,
// and is either `asc' or `desc'. Marker and Limit are used for pagination.
type ListOpts struct {
TenantID string `q:"tenant_id"`
Name string `q:"name"`
Description string `q:"description"`
Shared bool `q:"shared"`
Audited bool `q:"audited"`
ID string `q:"id"`
Limit int `q:"limit"`
Marker string `q:"marker"`
SortKey string `q:"sort_key"`
SortDir string `q:"sort_dir"`
}
// ToPolicyListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToPolicyListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return "", err
}
return q.String(), nil
}
// List returns a Pager which allows you to iterate over a collection of
// firewall policies. It accepts a ListOpts struct, which allows you to filter
// and sort the returned collection for greater efficiency.
//
// Default policy settings return only those firewall policies that are owned by the
// tenant who submits the request, unless an admin user submits the request.
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
url := rootURL(c)
if opts != nil {
query, err := opts.ToPolicyListQuery()
if err != nil {
return pagination.Pager{Err: err}
}
url += query
}
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
return PolicyPage{pagination.LinkedPageBase{PageResult: r}}
})
}
// CreateOptsBuilder is the interface options structs have to satisfy in order
// to be used in the main Create operation in this package. Since many
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type CreateOptsBuilder interface {
ToPolicyCreateMap() (map[string]interface{}, error)
}
// CreateOpts contains all the values needed to create a new firewall policy.
type CreateOpts struct {
// Only required if the caller has an admin role and wants to create a firewall policy
// for another tenant.
TenantID string
Name string
Description string
Shared *bool
Audited *bool
Rules []string
}
// ToPolicyCreateMap casts a CreateOpts struct to a map.
func (opts CreateOpts) ToPolicyCreateMap() (map[string]interface{}, error) {
p := make(map[string]interface{})
if opts.TenantID != "" {
p["tenant_id"] = opts.TenantID
}
if opts.Name != "" {
p["name"] = opts.Name
}
if opts.Description != "" {
p["description"] = opts.Description
}
if opts.Shared != nil {
p["shared"] = *opts.Shared
}
if opts.Audited != nil {
p["audited"] = *opts.Audited
}
if opts.Rules != nil {
p["firewall_rules"] = opts.Rules
}
return map[string]interface{}{"firewall_policy": p}, nil
}
// Create accepts a CreateOpts struct and uses the values to create a new firewall policy
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
var res CreateResult
reqBody, err := opts.ToPolicyCreateMap()
if err != nil {
res.Err = err
return res
}
_, res.Err = c.Request("POST", rootURL(c), gophercloud.RequestOpts{
JSONBody: &reqBody,
JSONResponse: &res.Body,
OkCodes: []int{201},
})
return res
}
// Get retrieves a particular firewall policy based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) GetResult {
var res GetResult
_, res.Err = c.Request("GET", resourceURL(c, id), gophercloud.RequestOpts{
JSONResponse: &res.Body,
OkCodes: []int{200},
})
return res
}
// UpdateOptsBuilder is the interface options structs have to satisfy in order
// to be used in the main Update operation in this package. Since many
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type UpdateOptsBuilder interface {
ToPolicyUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts contains the values used when updating a firewall policy.
type UpdateOpts struct {
// Name of the firewall policy.
Name string
Description string
Shared *bool
Audited *bool
Rules []string
}
// ToPolicyUpdateMap casts a CreateOpts struct to a map.
func (opts UpdateOpts) ToPolicyUpdateMap() (map[string]interface{}, error) {
p := make(map[string]interface{})
if opts.Name != "" {
p["name"] = opts.Name
}
if opts.Description != "" {
p["description"] = opts.Description
}
if opts.Shared != nil {
p["shared"] = *opts.Shared
}
if opts.Audited != nil {
p["audited"] = *opts.Audited
}
if opts.Rules != nil {
p["firewall_rules"] = opts.Rules
}
return map[string]interface{}{"firewall_policy": p}, nil
}
// Update allows firewall policies to be updated.
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
var res UpdateResult
reqBody, err := opts.ToPolicyUpdateMap()
if err != nil {
res.Err = err
return res
}
// Send request to API
_, res.Err = c.Request("PUT", resourceURL(c, id), gophercloud.RequestOpts{
JSONBody: &reqBody,
JSONResponse: &res.Body,
OkCodes: []int{200},
})
return res
}
// Delete will permanently delete a particular firewall policy based on its unique ID.
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
var res DeleteResult
_, res.Err = c.Request("DELETE", resourceURL(c, id), gophercloud.RequestOpts{
OkCodes: []int{204},
})
return res
}
func InsertRule(c *gophercloud.ServiceClient, policyID, ruleID, beforeID, afterID string) error {
type request struct {
RuleId string `json:"firewall_rule_id"`
Before string `json:"insert_before,omitempty"`
After string `json:"insert_after,omitempty"`
}
reqBody := request{
RuleId: ruleID,
Before: beforeID,
After: afterID,
}
// Send request to API
var res commonResult
_, res.Err = c.Request("PUT", insertURL(c, policyID), gophercloud.RequestOpts{
JSONBody: &reqBody,
JSONResponse: &res.Body,
OkCodes: []int{200},
})
return res.Err
}
func RemoveRule(c *gophercloud.ServiceClient, policyID, ruleID string) error {
type request struct {
RuleId string `json:"firewall_rule_id"`
}
reqBody := request{
RuleId: ruleID,
}
// Send request to API
var res commonResult
_, res.Err = c.Request("PUT", removeURL(c, policyID), gophercloud.RequestOpts{
JSONBody: &reqBody,
JSONResponse: &res.Body,
OkCodes: []int{200},
})
return res.Err
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment